]> source.dussan.org Git - vaadin-framework.git/commitdiff
Merge remote-tracking branch 'origin/master' into grid
authorArtur Signell <artur@vaadin.com>
Wed, 14 Jan 2015 08:18:39 +0000 (10:18 +0200)
committerArtur Signell <artur@vaadin.com>
Wed, 14 Jan 2015 08:18:39 +0000 (10:18 +0200)
Conflicts:
client/src/com/vaadin/client/communication/AtmospherePushConnection.java
server/tests/src/com/vaadin/data/fieldgroup/FieldGroupTests.java
shared/src/com/vaadin/shared/util/SharedUtil.java

Change-Id: I300b5a92bde562390a56b720adf9a37b795c9513

1  2 
client/src/com/vaadin/client/ApplicationConfiguration.java
client/src/com/vaadin/client/ApplicationConnection.java
client/src/com/vaadin/client/communication/AtmospherePushConnection.java
client/src/com/vaadin/client/extensions/ResponsiveConnector.java
server/src/com/vaadin/data/fieldgroup/FieldGroup.java
server/tests/src/com/vaadin/data/fieldgroup/FieldGroupTests.java
shared/src/com/vaadin/shared/util/SharedUtil.java

index 6abaf28eda2774a78ceb8ae6b4a139708cee1101,3431f064319b8219c2393903d850075333477acd..117486ffdb806df6191e311192dc1ded6d5389c7
@@@ -103,12 -106,8 +104,13 @@@ import com.vaadin.shared.communication.
  import com.vaadin.shared.communication.SharedState;
  import com.vaadin.shared.ui.ui.UIConstants;
  import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
+ import com.vaadin.shared.util.SharedUtil;
  
 +import elemental.json.Json;
 +import elemental.json.JsonArray;
 +import elemental.json.JsonObject;
 +import elemental.json.JsonValue;
 +
  /**
   * This is the client side communication "engine", managing client-server
   * communication with its server side counterpart
index dc8d497a69494386a8ca1148d69cbf00b8f53917,a2346db1866b15254087fa2b648a69cc5dbc1696..da08928f36ba1ef87467cf49bf79ff50e13e2279
@@@ -34,8 -35,8 +34,10 @@@ import com.vaadin.shared.Version
  import com.vaadin.shared.communication.PushConstants;
  import com.vaadin.shared.ui.ui.UIConstants;
  import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
+ import com.vaadin.shared.util.SharedUtil;
 +import elemental.json.JsonObject;
 +
  /**
   * The default {@link PushConnection} implementation that uses Atmosphere for
   * handling the communication channel.
index 0e7d682e395ccf36c9228f1c8eead0d6964498f0,fc267fc7dae287003b29201c8427dd04263c2bca..dce9f656b9029fd18286e0d29f548d6643b62af7
@@@ -2,9 -2,9 +2,10 @@@ package com.vaadin.data.fieldgroup
  
  import static org.hamcrest.MatcherAssert.assertThat;
  import static org.hamcrest.core.Is.is;
 +import static org.hamcrest.core.IsNull.nullValue;
  import static org.mockito.Mockito.mock;
  
+ import org.junit.Assert;
  import org.junit.Before;
  import org.junit.Test;
  
@@@ -39,10 -44,44 +45,51 @@@ public class FieldGroupTests 
          sut.bind(null, "foobar");
      }
  
 +    public void canUnbindWithoutItem() {
 +        sut.bind(field, "foobar");
 +
 +        sut.unbind(field);
 +        assertThat(sut.getField("foobar"), is(nullValue()));
 +    }
++
+     @Test
+     public void wrapInTransactionalProperty_provideCustomImpl_customTransactionalWrapperIsUsed() {
+         Bean bean = new Bean();
+         FieldGroup group = new FieldGroup() {
+             @Override
+             protected <T> Transactional<T> wrapInTransactionalProperty(
+                     Property<T> itemProperty) {
+                 return new TransactionalPropertyImpl(itemProperty);
+             }
+         };
+         group.setItemDataSource(new BeanItem<Bean>(bean));
+         TextField field = new TextField();
+         group.bind(field, "name");
+         Property propertyDataSource = field.getPropertyDataSource();
+         Assert.assertTrue("Custom implementation of transactional property "
+                 + "has not been used",
+                 propertyDataSource instanceof TransactionalPropertyImpl);
+     }
+     public static class TransactionalPropertyImpl<T> extends
+             TransactionalPropertyWrapper<T> {
+         public TransactionalPropertyImpl(Property<T> wrappedProperty) {
+             super(wrappedProperty);
+         }
+     }
+     public static class Bean {
+         private String name;
+         public String getName() {
+             return name;
+         }
+         public void setName(String name) {
+             this.name = name;
+         }
+     }
  }
index b40d8f03bb891f7f6f2009fdf36b583b07a1ff25,cc98d11abd6cdb3549a03d4a5ab39def7e77bc8e..206041235ade00c3aa776f2ce3d789715ee6bd05
@@@ -60,140 -60,45 +60,181 @@@ public class SharedUtil implements Seri
       */
      public static final String SIZE_PATTERN = "^(-?\\d*(?:\\.\\d+)?)(%|px|em|rem|ex|in|cm|mm|pt|pc)?$";
  
 -    
 +    /**
 +     * Splits a camelCaseString into an array of words with the casing
 +     * preserved.
 +     * 
 +     * @since 7.4
 +     * @param camelCaseString
 +     *            The input string in camelCase format
 +     * @return An array with one entry per word in the input string
 +     */
 +    public static String[] splitCamelCase(String camelCaseString) {
 +        StringBuilder sb = new StringBuilder();
 +        for (int i = 0; i < camelCaseString.length(); i++) {
 +            char c = camelCaseString.charAt(i);
 +            if (Character.isUpperCase(c) && isWordComplete(camelCaseString, i)) {
 +                sb.append(' ');
 +            }
 +            sb.append(c);
 +        }
 +        return sb.toString().split(" ");
 +    }
 +
 +    private static boolean isWordComplete(String camelCaseString, int i) {
 +        if (i == 0) {
 +            // Word can't end at the beginning
 +            return false;
 +        } else if (!Character.isUpperCase(camelCaseString.charAt(i - 1))) {
 +            // Word ends if previous char wasn't upper case
 +            return true;
 +        } else if (i + 1 < camelCaseString.length()
 +                && !Character.isUpperCase(camelCaseString.charAt(i + 1))) {
 +            // Word ends if next char isn't upper case
 +            return true;
 +        } else {
 +            return false;
 +        }
 +    }
 +
 +    /**
 +     * Converts a camelCaseString to a human friendly format (Camel case
 +     * string).
 +     * <p>
 +     * In general splits words when the casing changes but also handles special
 +     * cases such as consecutive upper case characters. Examples:
 +     * <p>
 +     * {@literal MyBeanContainer} becomes {@literal My Bean Container}
 +     * {@literal AwesomeURLFactory} becomes {@literal Awesome URL Factory}
 +     * {@literal SomeUriAction} becomes {@literal Some Uri Action}
 +     * 
 +     * @since 7.4
 +     * @param camelCaseString
 +     *            The input string in camelCase format
 +     * @return A human friendly version of the input
 +     */
 +    public static String camelCaseToHumanFriendly(String camelCaseString) {
 +        String[] parts = splitCamelCase(camelCaseString);
 +        for (int i = 0; i < parts.length; i++) {
 +            parts[i] = capitalize(parts[i]);
 +        }
 +        return join(parts, " ");
 +    }
 +
 +    private static boolean isAllUpperCase(String string) {
 +        for (int i = 0; i < string.length(); i++) {
 +            char c = string.charAt(i);
 +            if (!Character.isUpperCase(c) && !Character.isDigit(c)) {
 +                return false;
 +            }
 +        }
 +        return true;
 +    }
 +
 +    /**
 +     * Joins the words in the input array together into a single string by
 +     * inserting the separator string between each word.
 +     * 
 +     * @since 7.4
 +     * @param parts
 +     *            The array of words
 +     * @param separator
 +     *            The separator string to use between words
 +     * @return The constructed string of words and separators
 +     */
 +    public static String join(String[] parts, String separator) {
 +        StringBuilder sb = new StringBuilder();
 +        for (int i = 0; i < parts.length; i++) {
 +            sb.append(parts[i]);
 +            sb.append(separator);
 +        }
 +        return sb.substring(0, sb.length() - 1);
 +    }
 +
 +    /**
 +     * Capitalizes the first character in the given string
 +     * 
 +     * @since 7.4
 +     * @param string
 +     *            The string to capitalize
 +     * @return The capitalized string
 +     */
 +    public static String capitalize(String string) {
 +        if (string == null) {
 +            return null;
 +        }
 +
 +        if (string.length() <= 1) {
 +            return string.toUpperCase();
 +        }
 +
 +        return string.substring(0, 1).toUpperCase() + string.substring(1);
 +    }
 +
 +    /**
 +     * Converts a property id to a human friendly format. Handles nested
 +     * properties by only considering the last part, e.g. "address.streetName"
 +     * is equal to "streetName" for this method.
 +     * 
 +     * @since 7.4
 +     * @param propertyId
 +     *            The propertyId to format
 +     * @return A human friendly version of the property id
 +     */
 +    public static String propertyIdToHumanFriendly(Object propertyId) {
 +        String string = propertyId.toString();
 +        if (string.isEmpty()) {
 +            return "";
 +        }
 +
 +        // For nested properties, only use the last part
 +        int dotLocation = string.lastIndexOf('.');
 +        if (dotLocation > 0 && dotLocation < string.length() - 1) {
 +            string = string.substring(dotLocation + 1);
 +        }
 +
 +        return camelCaseToHumanFriendly(string);
 +    }
 +
+     /**
+      * Adds the get parameters to the uri and returns the new uri that contains
+      * the parameters.
+      *
+      * @param uri
+      *            The uri to which the parameters should be added.
+      * @param extraParams
+      *            One or more parameters in the format "a=b" or "c=d&e=f". An
+      *            empty string is allowed but will not modify the url.
+      * @return The modified URI with the get parameters in extraParams added.
+      */
+     public static String addGetParameters(String uri, String extraParams) {
+         if (extraParams == null || extraParams.length() == 0) {
+             return uri;
+         }
+         // RFC 3986: The query component is indicated by the first question
+         // mark ("?") character and terminated by a number sign ("#") character
+         // or by the end of the URI.
+         String fragment = null;
+         int hashPosition = uri.indexOf('#');
+         if (hashPosition != -1) {
+             // Fragment including "#"
+             fragment = uri.substring(hashPosition);
+             // The full uri before the fragment
+             uri = uri.substring(0, hashPosition);
+         }
 -    
++
+         if (uri.contains("?")) {
+             uri += "&";
+         } else {
+             uri += "?";
+         }
+         uri += extraParams;
 -    
++
+         if (fragment != null) {
+             uri += fragment;
+         }
++
+         return uri;
+     }
  }