]> source.dussan.org Git - vaadin-framework.git/commitdiff
Variable enhancements
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 25 Nov 2009 14:04:09 +0000 (14:04 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 25 Nov 2009 14:04:09 +0000 (14:04 +0000)
 * typing map for changevariable to <String,Object>
 * added variabletypes Object[] and Map<String,Object> where Objects can be Strings,Integers, Longs, Floats, Doubles, Booleans and Paintables (reference on client side translates to corresponding server side component by terminal)
 * Note, multilevel datastructures still not supported (Array or Map inside another), needs #3765

fixes #3756, #3757

svn changeset:10023/svn branch:6.2

15 files changed:
src/com/vaadin/terminal/VariableOwner.java
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/ui/VListSelect.java
src/com/vaadin/terminal/gwt/client/ui/VNativeSelect.java
src/com/vaadin/terminal/gwt/client/ui/VOptionGroup.java
src/com/vaadin/terminal/gwt/client/ui/VOptionGroupBase.java
src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
src/com/vaadin/terminal/gwt/client/ui/VTablePaging.java
src/com/vaadin/terminal/gwt/client/ui/VTextField.java
src/com/vaadin/terminal/gwt/client/ui/VTree.java
src/com/vaadin/terminal/gwt/client/ui/VTwinColSelect.java
src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
src/com/vaadin/ui/AbstractComponent.java
src/com/vaadin/ui/AbstractField.java
src/com/vaadin/ui/AbstractSelect.java

index 5f6fc038777e3f7823e974916e06651626d9e5ec..1507726b7dad4597ecb25674da1847fbfa2ab686 100644 (file)
@@ -33,7 +33,7 @@ public interface VariableOwner extends Serializable {
      * @param variables
      *            the Mapping from variable names to new variable values.
      */
-    public void changeVariables(Object source, Map variables);
+    public void changeVariables(Object source, Map<String, Object> variables);
 
     /**
      * <p>
index d461d2c6ca3932531a480431705ae39079fdee3e..02c05358e2bcb05faf6a73b5604c70dd6858d993 100755 (executable)
@@ -9,6 +9,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 import com.google.gwt.core.client.GWT;
@@ -216,7 +217,7 @@ public class ApplicationConnection {
      * <li><code>vaadin.postRequestHooks</code> is a map of functions which gets
      * called after each XHR made by vaadin application. Note, that it is
      * attaching js functions responsibility to create the variable like this:
-     *
+     * 
      * <code><pre>
      * if(!vaadin.postRequestHooks) {vaadin.postRequestHooks = new Object();}
      * postRequestHooks.myHook = function(appId) {
@@ -227,7 +228,7 @@ public class ApplicationConnection {
      * </pre></code> First parameter passed to these functions is the identifier
      * of Vaadin application that made the request.
      * </ul>
-     *
+     * 
      * TODO make this multi-app aware
      */
     private native void initializeClientHooks()
@@ -258,7 +259,7 @@ public class ApplicationConnection {
     /**
      * Runs possibly registered client side post request hooks. This is expected
      * to be run after each uidl request made by Vaadin application.
-     *
+     * 
      * @param appId
      */
     private static native void runPostRequestHooks(String appId)
@@ -281,7 +282,7 @@ public class ApplicationConnection {
     /**
      * Checks if client side is in debug mode. Practically this is invoked by
      * adding ?debug parameter to URI.
-     *
+     * 
      * @return true if client side is currently been debugged
      */
     public native static boolean isDebugMode()
@@ -356,7 +357,8 @@ public class ApplicationConnection {
             }
         }
         if (windowName != null && windowName.length() > 0) {
-            uri += (repaintAll || configuration.usePortletURLs() ? "&" : "?") + "windowName=" + windowName;
+            uri += (repaintAll || configuration.usePortletURLs() ? "&" : "?")
+                    + "windowName=" + windowName;
         }
 
         if (!forceSync) {
@@ -462,7 +464,7 @@ public class ApplicationConnection {
     /**
      * Shows the communication error notification. The 'details' only go to the
      * console for now.
-     *
+     * 
      * @param details
      *            Optional details for debugging.
      */
@@ -544,7 +546,7 @@ public class ApplicationConnection {
 
     /**
      * This method is called after applying uidl change set to application.
-     *
+     * 
      * It will clean current and queued variable change sets. And send next
      * change set if it exists.
      */
@@ -564,7 +566,7 @@ public class ApplicationConnection {
     /**
      * Cleans given queue of variable changes of such changes that came from
      * components that do not exist anymore.
-     *
+     * 
      * @param variableBurst
      */
     private void cleanVariableBurst(ArrayList<String> variableBurst) {
@@ -921,7 +923,7 @@ public class ApplicationConnection {
 
     /**
      * Returns Paintable element by its id
-     *
+     * 
      * @param id
      *            Paintable ID
      */
@@ -955,12 +957,12 @@ public class ApplicationConnection {
     /**
      * This method sends currently queued variable changes to server. It is
      * called when immediate variable update must happen.
-     *
+     * 
      * To ensure correct order for variable changes (due servers multithreading
      * or network), we always wait for active request to be handler before
      * sending a new one. If there is an active request, we will put varible
      * "burst" to queue that will be purged after current request is handled.
-     *
+     * 
      */
     @SuppressWarnings("unchecked")
     public void sendPendingVariableChanges() {
@@ -982,11 +984,11 @@ public class ApplicationConnection {
 
     /**
      * Build the variable burst and send it to server.
-     *
+     * 
      * When sync is forced, we also force sending of all pending variable-bursts
      * 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 forceSync
@@ -1060,6 +1062,64 @@ public class ApplicationConnection {
                 : "false", immediate, 'b');
     }
 
+    public void updateVariable(String paintableId, String variableName,
+            Map<String, Object> map, boolean immediate) {
+        final StringBuffer buf = new StringBuffer();
+        Iterator<String> iterator = map.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next();
+            Object value = map.get(key);
+            char transportType = getTransportType(value);
+            buf.append(transportType);
+            buf.append(key);
+            buf.append(VAR_ARRAYITEM_SEPARATOR);
+            if (transportType == 'p') {
+                buf.append(getPid((Paintable) value));
+            } else {
+                buf.append(value);
+            }
+
+            if (iterator.hasNext()) {
+                buf.append(VAR_ARRAYITEM_SEPARATOR);
+            }
+        }
+
+        addVariableToQueue(paintableId, variableName, buf.toString(),
+                immediate, 'm');
+    }
+
+    private char getTransportType(Object value) {
+        if (value instanceof String) {
+            return 's';
+        } else if (value instanceof Paintable) {
+            return 'p';
+        } else if (value instanceof Boolean) {
+            return 'b';
+        } else if (value instanceof Integer) {
+            return 'i';
+        } else if (value instanceof Float) {
+            return 'f';
+        } else if (value instanceof Double) {
+            return 'd';
+        } else if (value instanceof Long) {
+            return 'l';
+        }
+        return 'u';
+    }
+
+    public void updateVariable(String paintableId, String variableName,
+            String[] values, boolean immediate) {
+        final StringBuffer buf = new StringBuffer();
+        for (int i = 0; i < values.length; i++) {
+            if (i > 0) {
+                buf.append(VAR_ARRAYITEM_SEPARATOR);
+            }
+            buf.append(values[i]);
+        }
+        addVariableToQueue(paintableId, variableName, buf.toString(),
+                immediate, 'c');
+    }
+
     public void updateVariable(String paintableId, String variableName,
             Object[] values, boolean immediate) {
         final StringBuffer buf = new StringBuffer();
@@ -1067,7 +1127,15 @@ public class ApplicationConnection {
             if (i > 0) {
                 buf.append(VAR_ARRAYITEM_SEPARATOR);
             }
-            buf.append(values[i].toString());
+            Object value = values[i];
+            char transportType = getTransportType(value);
+            // first char tells the type in array
+            buf.append(transportType);
+            if (transportType == 'p') {
+                buf.append(getPid((Paintable) value));
+            } else {
+                buf.append(value);
+            }
         }
         addVariableToQueue(paintableId, variableName, buf.toString(),
                 immediate, 'a');
@@ -1075,9 +1143,9 @@ public class ApplicationConnection {
 
     /**
      * Update generic component features.
-     *
+     * 
      * <h2>Selecting correct implementation</h2>
-     *
+     * 
      * <p>
      * The implementation of a component depends on many properties, including
      * styles, component features, etc. Sometimes the user changes those
@@ -1085,21 +1153,21 @@ public class ApplicationConnection {
      * the beginning of your updateFromUIDL -method automatically replaces your
      * component with more appropriate if the requested implementation changes.
      * </p>
-     *
+     * 
      * <h2>Caption, icon, error messages and description</h2>
-     *
+     * 
      * <p>
      * Component can delegate management of caption, icon, error messages and
      * description to parent layout. This is optional an should be decided by
      * component author
      * </p>
-     *
+     * 
      * <h2>Component visibility and disabling</h2>
-     *
+     * 
      * This method will manage component visibility automatically and if
      * component is an instanceof FocusWidget, also handle component disabling
      * when needed.
-     *
+     * 
      * @param component
      *            Widget to be updated, expected to implement an instance of
      *            Paintable
@@ -1108,7 +1176,7 @@ public class ApplicationConnection {
      * @param manageCaption
      *            True if you want to delegate caption, icon, description and
      *            error message management to parent.
-     *
+     * 
      * @return Returns true iff no further painting is needed by caller
      */
     public boolean updateComponent(Widget component, UIDL uidl,
@@ -1318,7 +1386,7 @@ public class ApplicationConnection {
     /**
      * Traverses recursively child widgets until ContainerResizedListener child
      * widget is found. They will delegate it further if needed.
-     *
+     * 
      * @param container
      */
     private boolean runningLayout = false;
@@ -1381,7 +1449,7 @@ public class ApplicationConnection {
 
     /**
      * Converts relative sizes into pixel sizes.
-     *
+     * 
      * @param child
      * @return true if the child has a relative size
      */
@@ -1528,7 +1596,7 @@ public class ApplicationConnection {
 
     /**
      * Converts relative sizes into pixel sizes.
-     *
+     * 
      * @param child
      * @return true if the child has a relative size
      */
@@ -1545,12 +1613,12 @@ public class ApplicationConnection {
 
     /**
      * Get either existing or new Paintable for given UIDL.
-     *
+     * 
      * If corresponding Paintable has been previously painted, return it.
      * Otherwise create and register a new Paintable from UIDL. Caller must
      * update the returned Paintable from UIDL after it has been connected to
      * parent.
-     *
+     * 
      * @param uidl
      *            UIDL to create Paintable from.
      * @return Either existing or new Paintable corresponding to UIDL.
@@ -1570,7 +1638,7 @@ public class ApplicationConnection {
 
     /**
      * Returns a Paintable element by its root element
-     *
+     * 
      * @param element
      *            Root element of the paintable
      */
@@ -1584,7 +1652,7 @@ public class ApplicationConnection {
 
     /**
      * Singleton method to get instance of app's context menu.
-     *
+     * 
      * @return VContextMenu object
      */
     public VContextMenu getContextMenu() {
@@ -1600,7 +1668,7 @@ public class ApplicationConnection {
      * Translates custom protocols in UIDL URI's to be recognizable by browser.
      * All uri's from UIDL should be routed via this method before giving them
      * to browser due URI's in UIDL may contain custom protocols like theme://.
-     *
+     * 
      * @param uidlUri
      *            Vaadin URI from uidl
      * @return translated URI ready for browser
@@ -1628,7 +1696,7 @@ public class ApplicationConnection {
     /**
      * Listens for Notification hide event, and redirects. Used for system
      * messages, such as session expired.
-     *
+     * 
      */
     private class NotificationRedirect implements VNotification.EventListener {
         String url;
@@ -1648,9 +1716,9 @@ public class ApplicationConnection {
     /**
      * Data showed in tooltips are stored centrilized as it may be needed in
      * varios place: caption, layouts, and in owner components themselves.
-     *
+     * 
      * Updating TooltipInfo is done in updateComponent method.
-     *
+     * 
      */
     public TooltipInfo getTooltipTitleInfo(Paintable titleOwner, Object key) {
         if (null == titleOwner) {
@@ -1670,9 +1738,9 @@ public class ApplicationConnection {
      * Component may want to delegate Tooltip handling to client. Layouts add
      * Tooltip (description, errors) to caption, but some components may want
      * them to appear one other elements too.
-     *
+     * 
      * Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
-     *
+     * 
      * @param event
      * @param owner
      */
@@ -1685,9 +1753,9 @@ public class ApplicationConnection {
      * Component may want to delegate Tooltip handling to client. Layouts add
      * Tooltip (description, errors) to caption, but some components may want
      * them to appear one other elements too.
-     *
+     * 
      * Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
-     *
+     * 
      * @param event
      * @param owner
      * @param key
@@ -1701,7 +1769,7 @@ public class ApplicationConnection {
 
     /**
      * Adds PNG-fix conditionally (only for IE6) to the specified IMG -element.
-     *
+     * 
      * @param el
      *            the IMG element to fix
      */
@@ -1751,7 +1819,7 @@ public class ApplicationConnection {
      * Reset the name of the current browser-window. This should reflect the
      * window-name used in the server, but might be different from the
      * window-object target-name on client.
-     *
+     * 
      * @param stringAttribute
      *            New name for the window.
      */
@@ -1781,14 +1849,14 @@ public class ApplicationConnection {
      * <p>
      * This method can also be used to deregister tooltips by using null as
      * tooltip
-     *
+     * 
      * @param paintable
      *            Paintable "owning" this tooltip
      * @param key
      *            key assosiated with given tooltip. Can be any object. For
      *            example a related dom element. Same key must be given for
      *            {@link #handleTooltipEvent(Event, Paintable, Object)} method.
-     *
+     * 
      * @param tooltip
      *            the TooltipInfo object containing details shown in tooltip,
      *            null if deregistering tooltip
index e33231c81b0aa7fe52ad13b71997ad0d29a366da..480685345ffd8390265d38b7f0be935c26cd01f9 100644 (file)
@@ -60,14 +60,14 @@ public class VListSelect extends VOptionGroupBase {
     }
 
     @Override
-    protected Object[] getSelectedItems() {
-        final ArrayList selectedItemKeys = new ArrayList();
+    protected String[] getSelectedItems() {
+        final ArrayList<String> selectedItemKeys = new ArrayList<String>();
         for (int i = 0; i < select.getItemCount(); i++) {
             if (select.isItemSelected(i)) {
                 selectedItemKeys.add(select.getValue(i));
             }
         }
-        return selectedItemKeys.toArray();
+        return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);
     }
 
     @Override
index 50c7c337ba4398a92c7b5994d29ff320a74893b8..8c00e9c1a7a6232bcebbbc192c784ce95505faf0 100644 (file)
@@ -61,14 +61,14 @@ public class VNativeSelect extends VOptionGroupBase implements Field {
     }
 
     @Override
-    protected Object[] getSelectedItems() {
-        final ArrayList selectedItemKeys = new ArrayList();
+    protected String[] getSelectedItems() {
+        final ArrayList<String> selectedItemKeys = new ArrayList<String>();
         for (int i = 0; i < select.getItemCount(); i++) {
             if (select.isItemSelected(i)) {
                 selectedItemKeys.add(select.getValue(i));
             }
         }
-        return selectedItemKeys.toArray();
+        return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);
     }
 
     @Override
index e54cf04a6cdbcd7297cdcc60cb83b09af81f971a..a8ce1d124efe301445308858b5451d64f9406ef3 100644 (file)
@@ -58,8 +58,8 @@ public class VOptionGroup extends VOptionGroupBase {
     }\r
 \r
     @Override\r
-    protected Object[] getSelectedItems() {\r
-        return selectedKeys.toArray();\r
+    protected String[] getSelectedItems() {\r
+        return selectedKeys.toArray(new String[selectedKeys.size()]);\r
     }\r
 \r
     @Override\r
index a2c558094c92b037c14f687257f8e5b8f5eef247..115c4152893e62aef7906ea89fd6244c4c68ea66 100644 (file)
@@ -31,7 +31,7 @@ abstract class VOptionGroupBase extends Composite implements Paintable, Field,
 \r
     protected String id;\r
 \r
-    protected Set selectedKeys;\r
+    protected Set<String> selectedKeys;\r
 \r
     private boolean immediate;\r
 \r
@@ -215,10 +215,10 @@ abstract class VOptionGroupBase extends Composite implements Paintable, Field,
 \r
     protected abstract void buildOptions(UIDL uidl);\r
 \r
-    protected abstract Object[] getSelectedItems();\r
+    protected abstract String[] getSelectedItems();\r
 \r
-    protected Object getSelectedItem() {\r
-        final Object[] sel = getSelectedItems();\r
+    protected String getSelectedItem() {\r
+        final String[] sel = getSelectedItems();\r
         if (sel.length > 0) {\r
             return sel[0];\r
         } else {\r
index 575d35e5f09c93b044f15846db4d8014d0cafd05..e735dc67d9237c3f8ca7ef7c4e655ea97be98958 100644 (file)
@@ -1658,7 +1658,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler {
 
                 // update variable to server
                 client.updateVariable(paintableId, "collapsedcolumns",
-                        collapsedColumns.toArray(), false);
+                        collapsedColumns.toArray(new String[collapsedColumns
+                                .size()]), false);
                 // let rowRequestHandler determine proper rows
                 rowRequestHandler.refreshContent();
             }
@@ -2449,8 +2450,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler {
                                 // might
                                 // require changes to "clickEvent" immediateness
                                 // also.
-                                client.updateVariable(paintableId, "selected",
-                                        selectedRowKeys.toArray(), immediate);
+                                client
+                                        .updateVariable(
+                                                paintableId,
+                                                "selected",
+                                                selectedRowKeys
+                                                        .toArray(new String[selectedRowKeys
+                                                                .size()]),
+                                                immediate);
                             }
                             break;
                         case Event.ONCONTEXTMENU:
index 6995513524cc8103b233fd6b9eb009402db959eb..638f4b9be9d91de5a472f28c2ec959211dbe0766 100644 (file)
@@ -51,7 +51,7 @@ public class VTablePaging extends Composite implements Table, Paintable,
 
     private int selectMode = Table.SELECT_MODE_NONE;
 
-    private final ArrayList selectedRowKeys = new ArrayList();
+    private final ArrayList<String> selectedRowKeys = new ArrayList<String>();
 
     private int totalRows;
 
@@ -108,10 +108,11 @@ public class VTablePaging extends Composite implements Table, Paintable,
             }
 
             if (uidl.hasAttribute("selected")) {
-                final Set selectedKeys = uidl
+                final Set<String> selectedKeys = uidl
                         .getStringArrayVariableAsSet("selected");
                 selectedRowKeys.clear();
-                for (final Iterator it = selectedKeys.iterator(); it.hasNext();) {
+                for (final Iterator<String> it = selectedKeys.iterator(); it
+                        .hasNext();) {
                     selectedRowKeys.add(it.next());
                 }
             }
@@ -169,10 +170,10 @@ public class VTablePaging extends Composite implements Table, Paintable,
     /**
      * Updates row data from uidl. UpdateFromUIDL delegates updating tBody to
      * this method.
-     *
+     * 
      * Updates may be to different part of tBody, depending on update type. It
      * can be initial row data, scroll up, scroll down...
-     *
+     * 
      * @param uidl
      *            which contains row data
      */
@@ -299,7 +300,7 @@ public class VTablePaging extends Composite implements Table, Paintable,
     /**
      * Abstraction of table cell content. In needs to know on which row it is in
      * case of context click.
-     *
+     * 
      * @author mattitahvonen
      */
     public class BodyCell extends SimplePanel {
@@ -355,7 +356,7 @@ public class VTablePaging extends Composite implements Table, Paintable,
         /**
          * This method is used to set row status. Does not change value on
          * server.
-         *
+         * 
          * @param selected
          */
         public void setSelected(boolean sel) {
@@ -379,7 +380,7 @@ public class VTablePaging extends Composite implements Table, Paintable,
         /**
          * Toggles rows select state. Also updates state to server according to
          * tables immediate flag.
-         *
+         * 
          */
         public void toggleSelected() {
             if (selected) {
@@ -390,13 +391,13 @@ public class VTablePaging extends Composite implements Table, Paintable,
                 }
                 setSelected(true);
             }
-            client.updateVariable(id, "selected", selectedRowKeys.toArray(),
-                    immediate);
+            client.updateVariable(id, "selected", selectedRowKeys
+                    .toArray(new String[selectedRowKeys.size()]), immediate);
         }
 
         /**
          * Shows context menu for this row.
-         *
+         * 
          * @param event
          *            Event which triggered context menu. Correct place for
          *            context menu can be determined with it.
index 845a50e79389d78f1d1230ba871a21ac0e65e9df..8c02fc33cf492940a45e0f33d89948d2c34b81a5 100644 (file)
@@ -56,6 +56,7 @@ public class VTextField extends TextBoxBase implements Paintable, Field,
     private static final String ATTR_INPUTPROMPT = "prompt";
     private String inputPrompt = null;
     private boolean prompting = false;
+    private boolean listenFocus;
 
     public VTextField() {
         this(DOM.createInputText());
@@ -98,6 +99,8 @@ public class VTextField extends TextBoxBase implements Paintable, Field,
             setReadOnly(false);
         }
 
+        listenFocus = uidl.getBooleanAttribute("listenFocus");
+
         inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT);
 
         setMaxLength(uidl.hasAttribute("maxLength") ? uidl
@@ -195,6 +198,9 @@ public class VTextField extends TextBoxBase implements Paintable, Field,
             }
         }
         focusedTextField = this;
+        if (listenFocus) {
+            client.updateVariable(id, "focus", true, true);
+        }
     }
 
     public void onBlur(BlurEvent event) {
index 87d27caa55e5ecae4ab4efb0ddade298faea89b0..7769047c8024d099546780040de2d09ca53848d8 100644 (file)
@@ -169,8 +169,20 @@ public class VTree extends FlowPanel implements Paintable {
             selectedIds.remove(treeNode.key);
             treeNode.setSelected(false);
         }
-        client.updateVariable(paintableId, "selected", selectedIds.toArray(),
-                immediate);
+
+        Object[] foo = new Object[] { new Integer(33), new Float(3.2f),
+                new Long(222), this, "bar", true, new Double(3.33332) };
+        client.updateVariable(paintableId, "foo", foo, false);
+
+        HashMap<String, Object> bar = new HashMap<String, Object>();
+        bar.put("paintable", this);
+        bar.put("String", "bar");
+        bar.put("Integer", 33);
+
+        client.updateVariable(paintableId, "bar", bar, false);
+
+        client.updateVariable(paintableId, "selected", selectedIds
+                .toArray(new String[selectedIds.size()]), immediate);
     }
 
     public boolean isSelected(TreeNode treeNode) {
index 1694992074ddc8f3def5b997c2335989657856e9..880144a11ba482542ed0d163d95da9f767e7ce31 100644 (file)
@@ -110,12 +110,12 @@ public class VTwinColSelect extends VOptionGroupBase {
     }\r
 \r
     @Override\r
-    protected Object[] getSelectedItems() {\r
-        final ArrayList selectedItemKeys = new ArrayList();\r
+    protected String[] getSelectedItems() {\r
+        final ArrayList<String> selectedItemKeys = new ArrayList<String>();\r
         for (int i = 0; i < selections.getItemCount(); i++) {\r
             selectedItemKeys.add(selections.getValue(i));\r
         }\r
-        return selectedItemKeys.toArray();\r
+        return selectedItemKeys.toArray(new String[selectedItemKeys.size()]);\r
     }\r
 \r
     private boolean[] getItemsToAdd() {\r
@@ -162,8 +162,8 @@ public class VTwinColSelect extends VOptionGroupBase {
                     options.removeItem(optionIndex);\r
                 }\r
             }\r
-            client.updateVariable(id, "selected", selectedKeys.toArray(),\r
-                    isImmediate());\r
+            client.updateVariable(id, "selected", selectedKeys\r
+                    .toArray(new String[selectedKeys.size()]), isImmediate());\r
 \r
         } else if (event.getSource() == remove) {\r
             final boolean[] sel = getItemsToRemove();\r
@@ -181,8 +181,8 @@ public class VTwinColSelect extends VOptionGroupBase {
                     selections.removeItem(selectionIndex);\r
                 }\r
             }\r
-            client.updateVariable(id, "selected", selectedKeys.toArray(),\r
-                    isImmediate());\r
+            client.updateVariable(id, "selected", selectedKeys\r
+                    .toArray(new String[selectedKeys.size()]), isImmediate());\r
         } else if (event.getSource() == options) {\r
             // unselect all in other list, to avoid mistakes (i.e wrong button)\r
             final int c = selections.getItemCount();\r
index 7e9c04bc263626becef6f26a9d8b1c30b2b630bd..34d37fca0617c52a9b4ad92cd8c3df3e1b552eec 100644 (file)
@@ -70,7 +70,7 @@ import com.vaadin.ui.Upload.UploadException;
  * communication system between the client code (compiled with GWT into
  * JavaScript) and the server side components. Its client side counterpart is
  * {@link ApplicationConnection}.
- *
+ * 
  * A server side component sends its state to the client in a paint request (see
  * {@link Paintable} and {@link PaintTarget} on the server side). The client
  * widget receives these paint requests as calls to
@@ -78,7 +78,7 @@ import com.vaadin.ui.Upload.UploadException;
  * component communicates back to the server by sending a list of variable
  * changes (see {@link ApplicationConnection#updateVariable()} and
  * {@link VariableOwner#changeVariables(Object, Map)}).
- *
+ * 
  * TODO Document better!
  */
 @SuppressWarnings("serial")
@@ -87,13 +87,13 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * Generic interface of a (HTTP or Portlet) request to the application.
-     *
+     * 
      * This is a wrapper interface that allows
      * {@link AbstractCommunicationManager} to use a unified API.
-     *
+     * 
      * @see javax.servlet.ServletRequest
      * @see javax.portlet.PortletRequest
-     *
+     * 
      * @author peholmst
      */
     protected interface Request {
@@ -101,9 +101,9 @@ public abstract class AbstractCommunicationManager implements
         /**
          * Gets a {@link Session} wrapper implementation representing the
          * session for which this request was sent.
-         *
+         * 
          * Multiple Vaadin applications can be associated with a single session.
-         *
+         * 
          * @return Session
          */
         public Session getSession();
@@ -111,17 +111,17 @@ public abstract class AbstractCommunicationManager implements
         /**
          * Are the applications in this session running in a portlet or directly
          * as servlets.
-         *
+         * 
          * @return true if in a portlet
          */
         public boolean isRunningInPortlet();
 
         /**
          * Get the named HTTP or portlet request parameter.
-         *
+         * 
          * @see javax.servlet.ServletRequest#getParameter(String)
          * @see javax.portlet.PortletRequest#getParameter(String)
-         *
+         * 
          * @param name
          * @return
          */
@@ -130,7 +130,7 @@ public abstract class AbstractCommunicationManager implements
         /**
          * Returns the length of the request content that can be read from the
          * input stream returned by {@link #getInputStream()}.
-         *
+         * 
          * @return content length in bytes
          */
         public int getContentLength();
@@ -139,7 +139,7 @@ public abstract class AbstractCommunicationManager implements
          * Returns an input stream from which the request content can be read.
          * The request content length can be obtained with
          * {@link #getContentLength()} without reading the full stream contents.
-         *
+         * 
          * @return
          * @throws IOException
          */
@@ -148,7 +148,7 @@ public abstract class AbstractCommunicationManager implements
         /**
          * Returns the request identifier that identifies the target Vaadin
          * window for the request.
-         *
+         * 
          * @return String identifier for the request target window
          */
         public String getRequestID();
@@ -168,7 +168,7 @@ public abstract class AbstractCommunicationManager implements
         /**
          * Gets the underlying request object. The request is typically either a
          * {@link ServletRequest} or a {@link PortletRequest}.
-         *
+         * 
          * @return wrapped request object
          */
         public Object getWrappedRequest();
@@ -177,20 +177,20 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * Generic interface of a (HTTP or Portlet) response from the application.
-     *
+     * 
      * This is a wrapper interface that allows
      * {@link AbstractCommunicationManager} to use a unified API.
-     *
+     * 
      * @see javax.servlet.ServletResponse
      * @see javax.portlet.PortletResponse
-     *
+     * 
      * @author peholmst
      */
     protected interface Response {
 
         /**
          * Gets the output stream to which the response can be written.
-         *
+         * 
          * @return
          * @throws IOException
          */
@@ -199,7 +199,7 @@ public abstract class AbstractCommunicationManager implements
         /**
          * Sets the MIME content type for the response to be communicated to the
          * browser.
-         *
+         * 
          * @param type
          */
         public void setContentType(String type);
@@ -207,7 +207,7 @@ public abstract class AbstractCommunicationManager implements
         /**
          * Gets the wrapped response object, usually a class implementing either
          * {@link ServletResponse} or {@link PortletResponse}.
-         *
+         * 
          * @return wrapped request object
          */
         public Object getWrappedResponse();
@@ -216,14 +216,14 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * Generic wrapper interface for a (HTTP or Portlet) session.
-     *
+     * 
      * Several applications can be associated with a single session.
-     *
+     * 
      * TODO Document me!
-     *
+     * 
      * @see javax.servlet.http.HttpSession
      * @see javax.portlet.PortletSession
-     *
+     * 
      * @author peholmst
      */
     protected interface Session {
@@ -242,7 +242,7 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * TODO Document me!
-     *
+     * 
      * @author peholmst
      */
     protected interface Callback {
@@ -270,6 +270,17 @@ public abstract class AbstractCommunicationManager implements
     private static final int VAR_TYPE = 3;
     private static final int VAR_VALUE = 0;
 
+    private static final char VTYPE_PAINTABLE = 'p';
+    private static final char VTYPE_BOOLEAN = 'b';
+    private static final char VTYPE_DOUBLE = 'd';
+    private static final char VTYPE_FLOAT = 'f';
+    private static final char VTYPE_LONG = 'l';
+    private static final char VTYPE_INTEGER = 'i';
+    private static final char VTYPE_STRING = 's';
+    private static final char VTYPE_ARRAY = 'a';
+    private static final char VTYPE_STRINGARRAY = 'c';
+    private static final char VTYPE_MAP = 'm';
+
     private static final String VAR_RECORD_SEPARATOR = "\u001e";
 
     private static final String VAR_FIELD_SEPARATOR = "\u001f";
@@ -306,7 +317,7 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * TODO New constructor - document me!
-     *
+     * 
      * @param application
      */
     public AbstractCommunicationManager(Application application) {
@@ -317,26 +328,27 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Create an upload handler that is appropriate to the context in which the
      * application is being run (servlet or portlet).
-     *
+     * 
      * @return new {@link FileUpload} instance
      */
     protected abstract FileUpload createFileUpload();
 
     /**
      * TODO New method - document me!
-     *
+     * 
      * @param upload
      * @param request
      * @return
      * @throws IOException
      * @throws FileUploadException
      */
-    protected abstract FileItemIterator getUploadItemIterator(FileUpload upload,
-            Request request) throws IOException, FileUploadException;
+    protected abstract FileItemIterator getUploadItemIterator(
+            FileUpload upload, Request request) throws IOException,
+            FileUploadException;
 
     /**
      * TODO New method - document me!
-     *
+     * 
      * @param request
      * @param response
      * @throws IOException
@@ -431,12 +443,13 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * TODO document
-     *
+     * 
      * @param request
      * @param response
      * @throws IOException
      */
-    protected void sendUploadResponse(Request request, Response response) throws IOException {
+    protected void sendUploadResponse(Request request, Response response)
+            throws IOException {
         response.setContentType("text/html");
         final OutputStream out = response.getOutputStream();
         final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
@@ -448,19 +461,19 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * Internally process a UIDL request from the client.
-     *
+     * 
      * This method calls
      * {@link #handleVariables(Request, Response, Callback, Application, Window)}
      * to process any changes to variables by the client and then repaints
      * affected components using {@link #paintAfterVariableChanges()}.
-     *
+     * 
      * Also, some cleanup is done when a request arrives for an application that
      * has already been closed.
-     *
+     * 
      * The method handleUidlRequest(...) in subclasses should call this method.
-     *
+     * 
      * TODO better documentation
-     *
+     * 
      * @param request
      * @param response
      * @param callback
@@ -476,7 +489,7 @@ public abstract class AbstractCommunicationManager implements
         final OutputStream out;
 
         repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null);
-                //|| (request.getSession().isNew()); FIXME What the h*ll is this??
+        // || (request.getSession().isNew()); FIXME What the h*ll is this??
         out = response.getOutputStream();
 
         boolean analyzeLayouts = false;
@@ -554,13 +567,13 @@ public abstract class AbstractCommunicationManager implements
             }
         }
 
-        //out.flush(); - this line will cause errors when deployed on GateIn.
+        // out.flush(); - this line will cause errors when deployed on GateIn.
         out.close();
     }
 
     /**
      * TODO document
-     *
+     * 
      * @param request
      * @param response
      * @param callback
@@ -916,11 +929,11 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * TODO document
-     *
+     * 
      * If this method returns false, something was submitted that we did not
      * expect; this is probably due to the client being out-of-sync and sending
      * variable changes for non-existing pids
-     *
+     * 
      * @return true if successful, false if there was an inconsistency
      */
     private boolean handleVariables(Request request, Response response,
@@ -980,20 +993,19 @@ public abstract class AbstractCommunicationManager implements
                         // TODO this should be Map<String, Object>, but the
                         // VariableOwner API does not guarantee the key is a
                         // string
-                        Map<Object, Object> m;
+                        Map<String, Object> m;
                         if (nextVariable != null
                                 && variable[VAR_PID]
                                         .equals(nextVariable[VAR_PID])) {
                             // we have more than one value changes in row for
                             // one variable owner, collect em in HashMap
-                            m = new HashMap<Object, Object>();
+                            m = new HashMap<String, Object>();
                             m.put(variable[VAR_NAME], convertVariableValue(
                                     variable[VAR_TYPE].charAt(0),
                                     variable[VAR_VALUE]));
                         } else {
                             // use optimized single value map
-                            m = Collections.singletonMap(
-                                    (Object) variable[VAR_NAME],
+                            m = Collections.singletonMap(variable[VAR_NAME],
                                     convertVariableValue(variable[VAR_TYPE]
                                             .charAt(0), variable[VAR_VALUE]));
                         }
@@ -1084,7 +1096,7 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Reads the request data from the Request and returns it converted to an
      * UTF-8 string.
-     *
+     * 
      * @param request
      * @return
      * @throws IOException
@@ -1129,13 +1141,13 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Handles an error (exception) that occurred when processing variable
      * changes from the client or a failure of a file upload.
-     *
+     * 
      * For {@link AbstractField} components,
      * {@link AbstractField#handleError(com.vaadin.ui.AbstractComponent.ComponentErrorEvent)}
      * is called. In all other cases (or if the field does not handle the
      * error), {@link ErrorListener#terminalError(ErrorEvent)} for the
      * application error handler is called.
-     *
+     * 
      * @param application
      * @param owner
      *            component that the error concerns
@@ -1174,28 +1186,34 @@ public abstract class AbstractCommunicationManager implements
     private Object convertVariableValue(char variableType, String strValue) {
         Object val = null;
         switch (variableType) {
-        case 'a':
+        case VTYPE_ARRAY:
+            val = convertArray(strValue);
+            break;
+        case VTYPE_MAP:
+            val = convertMap(strValue);
+            break;
+        case VTYPE_STRINGARRAY:
             val = strValue.split(VAR_ARRAYITEM_SEPARATOR);
             break;
-        case 's':
+        case VTYPE_STRING:
             val = strValue;
             break;
-        case 'i':
+        case VTYPE_INTEGER:
             val = Integer.valueOf(strValue);
             break;
-        case 'l':
+        case VTYPE_LONG:
             val = Long.valueOf(strValue);
             break;
-        case 'f':
+        case VTYPE_FLOAT:
             val = Float.valueOf(strValue);
             break;
-        case 'd':
+        case VTYPE_DOUBLE:
             val = Double.valueOf(strValue);
             break;
-        case 'b':
+        case VTYPE_BOOLEAN:
             val = Boolean.valueOf(strValue);
             break;
-        case 'p':
+        case VTYPE_PAINTABLE:
             val = idPaintableMap.get(strValue);
             break;
         }
@@ -1203,11 +1221,35 @@ public abstract class AbstractCommunicationManager implements
         return val;
     }
 
+    private Object convertMap(String strValue) {
+        String[] parts = strValue.split(VAR_ARRAYITEM_SEPARATOR);
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        for (int i = 0; i < parts.length; i += 2) {
+            String key = parts[i];
+            char variabletype = key.charAt(0);
+            Object value = convertVariableValue(variabletype, parts[i + 1]);
+            map.put(key.substring(1), value);
+        }
+        return map;
+    }
+
+    private Object convertArray(String strValue) {
+        String[] val = strValue.split(VAR_ARRAYITEM_SEPARATOR);
+        Object[] values = new Object[val.length];
+        for (int i = 0; i < values.length; i++) {
+            String string = val[i];
+            // first char of string is typ
+            char variableType = string.charAt(0);
+            values[i] = convertVariableValue(variableType, string.substring(1));
+        }
+        return values;
+    }
+
     /**
-     * Prints the queued (pending) locale definitions to a {@link PrintWriter} in
-     * a (UIDL) format that can be sent to the client and used there in formatting
-     * dates, times etc.
-     *
+     * Prints the queued (pending) locale definitions to a {@link PrintWriter}
+     * in a (UIDL) format that can be sent to the client and used there in
+     * formatting dates, times etc.
+     * 
      * @param outWriter
      */
     private void printLocaleDeclarations(PrintWriter outWriter) {
@@ -1316,7 +1358,7 @@ public abstract class AbstractCommunicationManager implements
             final String timeformat = df.substring(timeStart, df.length());
             /*
              * Doesn't return second or milliseconds.
-             *
+             * 
              * We use timeformat to determine 12/24-hour clock
              */
             final boolean twelve_hour_clock = timeformat.indexOf("a") > -1;
@@ -1342,7 +1384,7 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * TODO New method - document me!
-     *
+     * 
      * @param request
      * @param callback
      * @param application
@@ -1429,11 +1471,11 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * Ends the Application.
-     *
+     * 
      * The browser is redirected to the Application logout URL set with
      * {@link Application#setLogoutURL(String)}, or to the application URL if no
      * logout URL is given.
-     *
+     * 
      * @param request
      *            the request instance.
      * @param response
@@ -1468,7 +1510,7 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Gets the Paintable Id. If Paintable has debug id set it will be used
      * prefixed with "PID_S". Otherwise a sequenced ID is created.
-     *
+     * 
      * @param paintable
      * @return the paintable Id.
      */
@@ -1514,7 +1556,7 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Returns dirty components which are in given window. Components in an
      * invisible subtrees are omitted.
-     *
+     * 
      * @param w
      *            root window for which dirty components is to be fetched
      * @return
@@ -1549,7 +1591,7 @@ public abstract class AbstractCommunicationManager implements
                             && !component.getParent().isVisible()) {
                         /*
                          * Do not return components in an invisible subtree.
-                         *
+                         * 
                          * Components that are invisible in visible subree, must
                          * be rendered (to let client know that they need to be
                          * hidden).
@@ -1576,7 +1618,7 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Internally mark a {@link Paintable} as painted and start collecting new
      * repaint requests for it.
-     *
+     * 
      * @param paintable
      */
     private void paintablePainted(Paintable paintable) {
@@ -1595,7 +1637,7 @@ public abstract class AbstractCommunicationManager implements
         private final Throwable throwable;
 
         /**
-         *
+         * 
          * @param owner
          * @param throwable
          */
@@ -1623,11 +1665,11 @@ public abstract class AbstractCommunicationManager implements
      * Queues a locale to be sent to the client (browser) for date and time
      * entry etc. All locale specific information is derived from server-side
      * {@link Locale} instances and sent to the client when needed, eliminating
-     * the need to use the {@link Locale} class and all the framework behind
-     * it on the client.
-     *
+     * the need to use the {@link Locale} class and all the framework behind it
+     * on the client.
+     * 
      * @see Locale#toString()
-     *
+     * 
      * @param value
      */
     public void requireLocale(String value) {
@@ -1644,9 +1686,9 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Constructs a {@link Locale} instance to be sent to the client based on a
      * short locale description string.
-     *
+     * 
      * @see #requireLocale(String)
-     *
+     * 
      * @param value
      * @return
      */
@@ -1687,7 +1729,7 @@ public abstract class AbstractCommunicationManager implements
 
     /**
      * Helper method to test if a component contains another
-     *
+     * 
      * @param parent
      * @param child
      */
@@ -1714,12 +1756,12 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Calls the Window URI handler for a request and returns the
      * {@link DownloadStream} returned by the handler.
-     *
+     * 
      * If the window is the main window of an application, the (deprecated)
      * {@link Application#handleURI(java.net.URL, String)} is called first to
      * handle {@link ApplicationResource}s, and the window handler is only
      * called if it returns null.
-     *
+     * 
      * @param window
      *            the target window of the request
      * @param request
@@ -1799,7 +1841,7 @@ public abstract class AbstractCommunicationManager implements
     /**
      * Helper class for terminal to keep track of data that client is expected
      * to know.
-     *
+     * 
      * TODO make customlayout templates (from theme) to be cached here.
      */
     class OpenWindowCache implements Serializable {
@@ -1807,7 +1849,7 @@ public abstract class AbstractCommunicationManager implements
         private Set<Object> res = new HashSet<Object>();
 
         /**
-         *
+         * 
          * @param paintable
          * @return true if the given class was added to cache
          */
index 2e6a0d6e19c47cc576891bd19ae89a6f38397a08..dbf988377ff94fabf8bcd052680156905c99f6d1 100644 (file)
@@ -820,7 +820,7 @@ public abstract class AbstractComponent implements Component, MethodEventSource
      * comment here, we use the default documentation from implemented
      * interface.
      */
-    public void changeVariables(Object source, Map variables) {
+    public void changeVariables(Object source, Map<String, Object> variables) {
     }
 
     /* General event framework */
index 9d1420a78d125aa08e44f5a3017c275940e395b6..d665650dd1f0cd541288795894ea08e5dd913684 100644 (file)
@@ -34,15 +34,15 @@ import com.vaadin.terminal.PaintTarget;
  * </p>
  * 
  * <p>
- * AbstractField also provides the {@link com.vaadin.data.Buffered}
- * interface for buffering the data source value. By default the Field is in
- * write through-mode and {@link #setWriteThrough(boolean)}should be called to
- * enable buffering.
+ * AbstractField also provides the {@link com.vaadin.data.Buffered} interface
+ * for buffering the data source value. By default the Field is in write
+ * through-mode and {@link #setWriteThrough(boolean)}should be called to enable
+ * buffering.
  * </p>
  * 
  * <p>
- * The class also supports {@link com.vaadin.data.Validator validators}
- * to make sure the value contained in the field is valid.
+ * The class also supports {@link com.vaadin.data.Validator validators} to make
+ * sure the value contained in the field is valid.
  * </p>
  * 
  * @author IT Mill Ltd.
@@ -940,7 +940,7 @@ public abstract class AbstractField extends AbstractComponent implements Field,
     }
 
     @Override
-    public void changeVariables(Object source, Map variables) {
+    public void changeVariables(Object source, Map<String, Object> variables) {
         super.changeVariables(source, variables);
 
     }
index 767fc21bd2131b95d7c9cc613548cb77682f7006..66cdaf8a658f7d698889a6d061f8692a5a4e34e1 100644 (file)
@@ -358,7 +358,7 @@ public abstract class AbstractSelect extends AbstractField implements
      *      java.util.Map)
      */
     @Override
-    public void changeVariables(Object source, Map variables) {
+    public void changeVariables(Object source, Map<String, Object> variables) {
         super.changeVariables(source, variables);
 
         // New option entered (and it is allowed)