]> source.dussan.org Git - vaadin-framework.git/commitdiff
#8277 Refactor client to server communication in preparation for RPC.
authorHenri Sara <hesara@vaadin.com>
Wed, 18 Jan 2012 12:23:06 +0000 (14:23 +0200)
committerHenri Sara <hesara@vaadin.com>
Wed, 25 Jan 2012 11:31:45 +0000 (13:31 +0200)
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/Util.java
src/com/vaadin/terminal/gwt/client/communication/MethodInvocation.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java

index af3fcefaf25df37838e52f53062df9ada8f53cad..a7f146be16fc9879a2108ff3be09938caaf03394 100644 (file)
@@ -36,6 +36,7 @@ import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage;
 import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
 import com.vaadin.terminal.gwt.client.RenderInformation.Size;
+import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
 import com.vaadin.terminal.gwt.client.ui.Field;
 import com.vaadin.terminal.gwt.client.ui.VContextMenu;
 import com.vaadin.terminal.gwt.client.ui.VNotification;
@@ -73,6 +74,8 @@ public class ApplicationConnection {
 
     private static final String ERROR_CLASSNAME_EXT = "-error";
 
+    public static final String UPDATE_VARIABLE_METHOD = "v";
+
     public static final char VAR_RECORD_SEPARATOR = '\u001e';
 
     public static final char VAR_FIELD_SEPARATOR = '\u001f';
@@ -106,7 +109,7 @@ public class ApplicationConnection {
 
     private final HashMap<String, String> resourcesMap = new HashMap<String, String>();
 
-    private final ArrayList<String> pendingVariables = new ArrayList<String>();
+    private ArrayList<MethodInvocation> pendingInvocations = new ArrayList<MethodInvocation>();
 
     private WidgetSet widgetSet;
 
@@ -129,7 +132,7 @@ public class ApplicationConnection {
     private ApplicationConfiguration configuration;
 
     /** List of pending variable change bursts that must be submitted in order */
-    private final ArrayList<ArrayList<String>> pendingVariableBursts = new ArrayList<ArrayList<String>>();
+    private final ArrayList<ArrayList<MethodInvocation>> pendingBursts = new ArrayList<ArrayList<MethodInvocation>>();
 
     /** Timer for automatic refirect to SessionExpiredURL */
     private Timer redirectTimer;
@@ -750,14 +753,14 @@ public class ApplicationConnection {
      * change set if it exists.
      */
     private void checkForPendingVariableBursts() {
-        cleanVariableBurst(pendingVariables);
-        if (pendingVariableBursts.size() > 0) {
-            for (Iterator<ArrayList<String>> iterator = pendingVariableBursts
+        cleanVariableBurst(pendingInvocations);
+        if (pendingBursts.size() > 0) {
+            for (Iterator<ArrayList<MethodInvocation>> iterator = pendingBursts
                     .iterator(); iterator.hasNext();) {
                 cleanVariableBurst(iterator.next());
             }
-            ArrayList<String> nextBurst = pendingVariableBursts.get(0);
-            pendingVariableBursts.remove(0);
+            ArrayList<MethodInvocation> nextBurst = pendingBursts.get(0);
+            pendingBursts.remove(0);
             buildAndSendVariableBurst(nextBurst, false);
         }
     }
@@ -768,16 +771,13 @@ public class ApplicationConnection {
      * 
      * @param variableBurst
      */
-    private void cleanVariableBurst(ArrayList<String> variableBurst) {
-        for (int i = 1; i < variableBurst.size(); i += 2) {
-            String id = variableBurst.get(i);
-            id = id.substring(0, id.indexOf(VAR_FIELD_SEPARATOR));
+    private void cleanVariableBurst(ArrayList<MethodInvocation> variableBurst) {
+        for (int i = 1; i < variableBurst.size(); i++) {
+            String id = variableBurst.get(i).getPaintableId();
             if (!getPaintableMap().hasPaintable(id)
                     && !getPaintableMap().isDragAndDropPaintable(id)) {
                 // variable owner does not exist anymore
-                variableBurst.remove(i - 1);
-                variableBurst.remove(i - 1);
-                i -= 2;
+                variableBurst.remove(i);
                 VConsole.log("Removed variable from removed component: " + id);
             }
         }
@@ -1108,17 +1108,16 @@ public class ApplicationConnection {
 
     private void addVariableToQueue(String paintableId, String variableName,
             String encodedValue, boolean immediate, char type) {
-        final String id = paintableId + VAR_FIELD_SEPARATOR + variableName
-                + VAR_FIELD_SEPARATOR + type;
-        for (int i = 1; i < pendingVariables.size(); i += 2) {
-            if ((pendingVariables.get(i)).equals(id)) {
-                pendingVariables.remove(i - 1);
-                pendingVariables.remove(i - 1);
-                break;
-            }
-        }
-        pendingVariables.add(encodedValue);
-        pendingVariables.add(id);
+        // TODO could eliminate invocations of same shared variable setter
+        String param = variableName + VAR_FIELD_SEPARATOR + type
+                + VAR_FIELD_SEPARATOR + encodedValue;
+        addMethodInvocationToQueue(paintableId, new MethodInvocation(
+                paintableId, UPDATE_VARIABLE_METHOD, param), immediate);
+    }
+
+    private void addMethodInvocationToQueue(String paintableId,
+            MethodInvocation invocation, boolean immediate) {
+        pendingInvocations.add(invocation);
         if (immediate) {
             sendPendingVariableChanges();
         }
@@ -1154,15 +1153,12 @@ public class ApplicationConnection {
         if (applicationRunning) {
             if (hasActiveRequest()) {
                 // skip empty queues if there are pending bursts to be sent
-                if (pendingVariables.size() > 0
-                        || pendingVariableBursts.size() == 0) {
-                    ArrayList<String> burst = (ArrayList<String>) pendingVariables
-                            .clone();
-                    pendingVariableBursts.add(burst);
-                    pendingVariables.clear();
+                if (pendingInvocations.size() > 0 || pendingBursts.size() == 0) {
+                    pendingBursts.add(pendingInvocations);
+                    pendingInvocations = new ArrayList<MethodInvocation>();
                 }
             } else {
-                buildAndSendVariableBurst(pendingVariables, false);
+                buildAndSendVariableBurst(pendingInvocations, false);
             }
         }
     }
@@ -1174,35 +1170,38 @@ public class ApplicationConnection {
      * at the same time. This is ok as we can assume that DOM will never be
      * updated after this.
      * 
-     * @param pendingVariables
-     *            Vector of variable changes to send
+     * @param pendingInvocations
+     *            List of RPC method invocations to send
      * @param forceSync
      *            Should we use synchronous request?
      */
-    private void buildAndSendVariableBurst(ArrayList<String> pendingVariables,
-            boolean forceSync) {
+    private void buildAndSendVariableBurst(
+            ArrayList<MethodInvocation> pendingInvocations, boolean forceSync) {
         final StringBuffer req = new StringBuffer();
 
-        while (!pendingVariables.isEmpty()) {
+        while (!pendingInvocations.isEmpty()) {
             if (ApplicationConfiguration.isDebugMode()) {
-                Util.logVariableBurst(this, pendingVariables);
+                Util.logVariableBurst(this, pendingInvocations);
             }
-            for (int i = 0; i < pendingVariables.size(); i++) {
+            // TODO use JSON for messages
+            for (int i = 0; i < pendingInvocations.size(); i++) {
                 if (i > 0) {
-                    if (i % 2 == 0) {
-                        req.append(VAR_RECORD_SEPARATOR);
-                    } else {
-                        req.append(VAR_FIELD_SEPARATOR);
-                    }
+                    req.append(VAR_RECORD_SEPARATOR);
                 }
-                req.append(pendingVariables.get(i));
+                MethodInvocation invocation = pendingInvocations.get(i);
+                req.append(invocation.getPaintableId());
+                req.append(VAR_FIELD_SEPARATOR);
+                req.append(invocation.getMethodName());
+                req.append(VAR_FIELD_SEPARATOR);
+                // TODO support multiple parameters
+                req.append(invocation.getParameters());
             }
 
-            pendingVariables.clear();
-            // Append all the busts to this synchronous request
-            if (forceSync && !pendingVariableBursts.isEmpty()) {
-                pendingVariables = pendingVariableBursts.get(0);
-                pendingVariableBursts.remove(0);
+            pendingInvocations.clear();
+            // Append all the bursts to this synchronous request
+            if (forceSync && !pendingBursts.isEmpty()) {
+                pendingInvocations = pendingBursts.get(0);
+                pendingBursts.remove(0);
                 req.append(VAR_BURST_SEPARATOR);
             }
         }
index 597ca3d49ca43bbc4fdc50a5151ba16c981a91b0..2789a730781bda628e437fad93300e3e1c39fa69 100644 (file)
@@ -30,6 +30,7 @@ import com.google.gwt.user.client.ui.HasWidgets;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
+import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
 
 public class Util {
 
@@ -936,45 +937,60 @@ public class Util {
         return idx;
     }
 
-    private static void printPaintablesVariables(ArrayList<String[]> vars,
-            String id, ApplicationConnection c) {
+    private static void printPaintablesInvocations(
+            ArrayList<MethodInvocation> invocations, String id,
+            ApplicationConnection c) {
         VPaintableWidget paintable = (VPaintableWidget) VPaintableMap.get(c)
                 .getPaintable(id);
         if (paintable != null) {
             VConsole.log("\t" + id + " (" + paintable.getClass() + ") :");
-            for (String[] var : vars) {
-                VConsole.log("\t\t" + var[1] + " (" + var[2] + ")" + " : "
-                        + var[0]);
+            for (MethodInvocation invocation : invocations) {
+                String formattedParams = invocation.getParameters();
+                if (ApplicationConnection.UPDATE_VARIABLE_METHOD
+                        .equals(invocation.getMethodName())) {
+                    // if an updateVariable call, format as variable changes
+                    // ensure with limit that also trailing parameters are
+                    // included
+                    String[] split = invocation
+                            .getParameters()
+                            .split(String
+                                    .valueOf(ApplicationConnection.VAR_FIELD_SEPARATOR),
+                                    3);
+
+                    // unless of correct length, do not reformat
+                    if (split.length == 3) {
+                        // TODO needs to be reworked
+                        // name, type, value
+                        formattedParams = split[0] + " (" + split[1] + ")"
+                                + " : " + split[2];
+                    }
+                }
+                VConsole.log("\t\t" + invocation.getMethodName() + "("
+                        + formattedParams + ")");
             }
         }
     }
 
     static void logVariableBurst(ApplicationConnection c,
-            ArrayList<String> loggedBurst) {
+            ArrayList<MethodInvocation> loggedBurst) {
         try {
             VConsole.log("Variable burst to be sent to server:");
             String curId = null;
-            ArrayList<String[]> vars = new ArrayList<String[]>();
+            ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>();
             for (int i = 0; i < loggedBurst.size(); i++) {
-                String value = loggedBurst.get(i++);
-                String[] split = loggedBurst
-                        .get(i)
-                        .split(String
-                                .valueOf(ApplicationConnection.VAR_FIELD_SEPARATOR));
-                String id = split[0];
+                String id = loggedBurst.get(i).getPaintableId();
 
                 if (curId == null) {
                     curId = id;
                 } else if (!curId.equals(id)) {
-                    printPaintablesVariables(vars, curId, c);
-                    vars.clear();
+                    printPaintablesInvocations(invocations, curId, c);
+                    invocations.clear();
                     curId = id;
                 }
-                split[0] = value;
-                vars.add(split);
+                invocations.add(loggedBurst.get(i));
             }
-            if (!vars.isEmpty()) {
-                printPaintablesVariables(vars, curId, c);
+            if (!invocations.isEmpty()) {
+                printPaintablesInvocations(invocations, curId, c);
             }
         } catch (Exception e) {
             VConsole.error(e);
diff --git a/src/com/vaadin/terminal/gwt/client/communication/MethodInvocation.java b/src/com/vaadin/terminal/gwt/client/communication/MethodInvocation.java
new file mode 100644 (file)
index 0000000..c07427f
--- /dev/null
@@ -0,0 +1,34 @@
+package com.vaadin.terminal.gwt.client.communication;
+
+/**
+ * Information needed by the framework to send an RPC method invocation from the
+ * client to the server or vice versa.
+ * 
+ * @since 7.0
+ */
+public class MethodInvocation {
+
+    private final String paintableId;
+    private final String methodName;
+    private final String parameters;
+
+    // TODO Parameters should be an Object[]?
+    public MethodInvocation(String paintableId, String methodName,
+            String parameters) {
+        this.paintableId = paintableId;
+        this.methodName = methodName;
+        this.parameters = parameters;
+    }
+
+    public String getPaintableId() {
+        return paintableId;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    public String getParameters() {
+        return parameters;
+    }
+}
\ No newline at end of file
index 86f2c7a2debfb160a06d6958f6ef1497c8f4c8b6..c71bb0ea10fc085af15ae01d044961a2ee9db66f 100644 (file)
@@ -123,10 +123,11 @@ public abstract class AbstractCommunicationManager implements
     private static final String WRITE_SECURITY_TOKEN_FLAG = "writeSecurityToken";
 
     /* Variable records indexes */
-    private static final int VAR_PID = 1;
-    private static final int VAR_NAME = 2;
+    private static final int VAR_PID = 0;
+    private static final int VAR_METHOD = 1;
+    private static final int VAR_VARNAME = 2;
     private static final int VAR_TYPE = 3;
-    private static final int VAR_VALUE = 0;
+    private static final int VAR_VALUE = 4;
 
     private static final char VTYPE_PAINTABLE = 'p';
     private static final char VTYPE_BOOLEAN = 'b';
@@ -1151,8 +1152,7 @@ public abstract class AbstractCommunicationManager implements
 
             for (int bi = 1; bi < bursts.length; bi++) {
                 final String burst = bursts[bi];
-                success = handleVariableBurst(request, application2, success,
-                        burst);
+                success = handleBurst(request, application2, success, burst);
 
                 // In case that there were multiple bursts, we know that this is
                 // a special synchronous case for closing window. Thus we are
@@ -1182,14 +1182,16 @@ public abstract class AbstractCommunicationManager implements
         return success;
     }
 
-    public boolean handleVariableBurst(Object source, Application app,
-            boolean success, final String burst) {
+    public boolean handleBurst(Object source, Application app, boolean success,
+            final String burst) {
         // extract variables to two dim string array
         final String[] tmp = burst.split(String.valueOf(VAR_RECORD_SEPARATOR));
-        final String[][] variableRecords = new String[tmp.length][4];
+        // TODO support variable number of parameters
+        final String[][] variableRecords = new String[tmp.length][5];
         for (int i = 0; i < tmp.length; i++) {
-            variableRecords[i] = tmp[i].split(String
-                    .valueOf(VAR_FIELD_SEPARATOR));
+            // ensure with limit that also trailing parameters are included
+            variableRecords[i] = tmp[i].split(
+                    String.valueOf(VAR_FIELD_SEPARATOR), 5);
         }
 
         for (int i = 0; i < variableRecords.length; i++) {
@@ -1199,6 +1201,12 @@ public abstract class AbstractCommunicationManager implements
                 nextVariable = variableRecords[i + 1];
             }
             final VariableOwner owner = getVariableOwner(variable[VAR_PID]);
+            final String methodName = variable[VAR_METHOD];
+            if (!ApplicationConnection.UPDATE_VARIABLE_METHOD
+                    .equals(methodName)) {
+                // TODO handle other RPC calls
+                continue;
+            }
             if (owner != null && owner.isEnabled()) {
                 Map<String, Object> m;
                 if (nextVariable != null
@@ -1206,13 +1214,13 @@ public abstract class AbstractCommunicationManager implements
                     // we have more than one value changes in row for
                     // one variable owner, collect them in HashMap
                     m = new HashMap<String, Object>();
-                    m.put(variable[VAR_NAME],
+                    m.put(variable[VAR_VARNAME],
                             convertVariableValue(variable[VAR_TYPE].charAt(0),
                                     variable[VAR_VALUE]));
                 } else {
                     // use optimized single value map
                     m = Collections.singletonMap(
-                            variable[VAR_NAME],
+                            variable[VAR_VARNAME],
                             convertVariableValue(variable[VAR_TYPE].charAt(0),
                                     variable[VAR_VALUE]));
                 }
@@ -1227,7 +1235,7 @@ public abstract class AbstractCommunicationManager implements
                     } else {
                         nextVariable = null;
                     }
-                    m.put(variable[VAR_NAME],
+                    m.put(variable[VAR_VARNAME],
                             convertVariableValue(variable[VAR_TYPE].charAt(0),
                                     variable[VAR_VALUE]));
                 }
@@ -1246,7 +1254,7 @@ public abstract class AbstractCommunicationManager implements
                 // Handle special case where window-close is called
                 // after the window has been removed from the
                 // application or the application has closed
-                if ("close".equals(variable[VAR_NAME])
+                if ("close".equals(variable[VAR_VARNAME])
                         && "true".equals(variable[VAR_VALUE])) {
                     // Silently ignore this
                     continue;