From d4a4cc148bb3097c0db85577b7ad2ed255f13697 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Wed, 4 Apr 2012 18:04:52 +0300 Subject: [PATCH] #8602 Added support for Map --- .../gwt/client/communication/JsonDecoder.java | 18 +++++++++++ .../gwt/client/communication/JsonEncoder.java | 26 ++++++++++++--- .../gwt/client/ui/CssLayoutConnector.java | 11 ++++--- .../vaadin/terminal/gwt/server/JsonCodec.java | 32 +++++++++++++++++-- src/com/vaadin/ui/CssLayout.java | 4 +-- 5 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index 86a64cb47c..2b58c13f3e 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -17,6 +17,7 @@ import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONString; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.client.ServerConnector; @@ -63,6 +64,8 @@ public class JsonDecoder { val = decodeArray((JSONArray) value, idMapper, connection); } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { val = decodeMap((JSONObject) value, idMapper, connection); + } else if (JsonEncoder.VTYPE_MAP_CONNECTOR.equals(variableType)) { + val = decodeConnectorMap((JSONObject) value, idMapper, connection); } else if (JsonEncoder.VTYPE_LIST.equals(variableType)) { val = decodeList((JSONArray) value, idMapper, connection); } else if (JsonEncoder.VTYPE_SET.equals(variableType)) { @@ -114,6 +117,21 @@ public class JsonDecoder { return map; } + private static Map decodeConnectorMap( + JSONObject jsonMap, ConnectorMap idMapper, + ApplicationConnection connection) { + HashMap map = new HashMap(); + Iterator it = jsonMap.keySet().iterator(); + while (it.hasNext()) { + String connectorId = it.next(); + Connector connector = idMapper.getConnector(connectorId); + map.put(connector, + decodeValue((JSONArray) jsonMap.get(connectorId), idMapper, + connection)); + } + return map; + } + private static String[] decodeStringArray(JSONArray jsonArray) { int size = jsonArray.size(); List tokens = new ArrayList(size); diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index 1215743790..294626e71a 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -42,6 +42,10 @@ public class JsonEncoder { public static final String VTYPE_ARRAY = "a"; public static final String VTYPE_STRINGARRAY = "S"; public static final String VTYPE_MAP = "m"; + // Hack to support Map. Should be replaced by generic support + // for any object as key (#8602) + @Deprecated + public static final String VTYPE_MAP_CONNECTOR = "M"; public static final String VTYPE_LIST = "L"; public static final String VTYPE_SET = "q"; public static final String VTYPE_NULL = "n"; @@ -77,14 +81,26 @@ public class JsonEncoder { } else if (value instanceof Object[]) { return encodeObjectArray((Object[]) value, connectorMap, connection); } else if (value instanceof Map) { - Map map = (Map) value; + Map map = (Map) value; JSONObject jsonMap = new JSONObject(); - for (String mapKey : map.keySet()) { - // TODO handle object graph loops? + String type = VTYPE_MAP; + for (Object mapKey : map.keySet()) { Object mapValue = map.get(mapKey); - jsonMap.put(mapKey, encode(mapValue, connectorMap, connection)); + if (mapKey instanceof Connector) { + mapKey = ((Connector) mapKey).getConnectorId(); + type = VTYPE_MAP_CONNECTOR; + } + + if (!(mapKey instanceof String)) { + throw new RuntimeException( + "Only Map and Map is currently supported." + + " Failed map used " + + mapKey.getClass().getName() + " as keys"); + } + jsonMap.put((String) mapKey, + encode(mapValue, connectorMap, connection)); } - return combineTypeAndValue(VTYPE_MAP, jsonMap); + return combineTypeAndValue(type, jsonMap); } else if (value instanceof Connector) { Connector connector = (Connector) value; return combineTypeAndValue(VTYPE_CONNECTOR, new JSONString( diff --git a/src/com/vaadin/terminal/gwt/client/ui/CssLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/CssLayoutConnector.java index 7d375501db..554cec0d36 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/CssLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/CssLayoutConnector.java @@ -12,6 +12,7 @@ import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ComponentConnector; +import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VCaption; @@ -25,13 +26,13 @@ import com.vaadin.ui.CssLayout; public class CssLayoutConnector extends AbstractLayoutConnector { public static class CssLayoutState extends AbstractLayoutState { - private Map childCss = new HashMap(); + private Map childCss = new HashMap(); - public Map getChildCss() { + public Map getChildCss() { return childCss; } - public void setChildCss(Map childCss) { + public void setChildCss(Map childCss) { this.childCss = childCss; } @@ -79,10 +80,10 @@ public class CssLayoutConnector extends AbstractLayoutConnector { new VMarginInfo(getState().getMarginsBitmask())); for (ComponentConnector child : getChildren()) { - if (!getState().getChildCss().containsKey(child.getConnectorId())) { + if (!getState().getChildCss().containsKey(child)) { continue; } - String css = getState().getChildCss().get(child.getConnectorId()); + String css = getState().getChildCss().get(child); Style style = child.getWidget().getElement().getStyle(); // should we remove styles also? How can we know what we have added // as it is added directly to the child component? diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index 21a189a435..15be2673ba 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -90,6 +90,8 @@ public class JsonCodec implements Serializable { val = decodeList((JSONArray) value, application); } else if (JsonEncoder.VTYPE_SET.equals(variableType)) { val = decodeSet((JSONArray) value, application); + } else if (JsonEncoder.VTYPE_MAP_CONNECTOR.equals(variableType)) { + val = decodeConnectorMap((JSONObject) value, application); } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { val = decodeMap((JSONObject) value, application); } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) { @@ -135,6 +137,19 @@ public class JsonCodec implements Serializable { return map; } + private static Object decodeConnectorMap(JSONObject jsonMap, + Application application) throws JSONException { + HashMap map = new HashMap(); + Iterator it = jsonMap.keys(); + while (it.hasNext()) { + String connectorId = it.next(); + Connector connector = application.getConnector(connectorId); + map.put(connector, + decode(jsonMap.getJSONArray(connectorId), application)); + } + return map; + } + private static String[] decodeStringArray(JSONArray jsonArray) throws JSONException { int length = jsonArray.length(); @@ -227,7 +242,14 @@ public class JsonCodec implements Serializable { } else if (value instanceof Map) { Map map = (Map) value; JSONObject jsonMap = encodeMapContents(map, application); - return combineTypeAndValue(JsonEncoder.VTYPE_MAP, jsonMap); + // Hack to support Connector as map key. Should be fixed by # + if (!map.isEmpty() + && map.keySet().iterator().next() instanceof Connector) { + return combineTypeAndValue(JsonEncoder.VTYPE_MAP_CONNECTOR, + jsonMap); + } else { + return combineTypeAndValue(JsonEncoder.VTYPE_MAP, jsonMap); + } } else if (value instanceof Connector) { Connector connector = (Connector) value; return combineTypeAndValue(JsonEncoder.VTYPE_CONNECTOR, @@ -328,12 +350,16 @@ public class JsonCodec implements Serializable { Application application) throws JSONException { JSONObject jsonMap = new JSONObject(); for (Object mapKey : map.keySet()) { + Object mapValue = map.get(mapKey); + + if (mapKey instanceof ClientConnector) { + mapKey = ((ClientConnector) mapKey).getConnectorId(); + } if (!(mapKey instanceof String)) { throw new JSONException( - "Only maps with String keys are currently supported (#8602)"); + "Only maps with String/Connector keys are currently supported (#8602)"); } - Object mapValue = map.get(mapKey); jsonMap.put((String) mapKey, encode(mapValue, application)); } return jsonMap; diff --git a/src/com/vaadin/ui/CssLayout.java b/src/com/vaadin/ui/CssLayout.java index 27dc9b8306..5c14d55d11 100644 --- a/src/com/vaadin/ui/CssLayout.java +++ b/src/com/vaadin/ui/CssLayout.java @@ -11,7 +11,6 @@ import com.vaadin.event.LayoutEvents.LayoutClickListener; import com.vaadin.event.LayoutEvents.LayoutClickNotifier; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.MouseEventDetails; -import com.vaadin.terminal.gwt.client.ui.CssLayoutConnector; import com.vaadin.terminal.gwt.client.ui.CssLayoutConnector.CssLayoutServerRPC; import com.vaadin.terminal.gwt.client.ui.CssLayoutConnector.CssLayoutState; import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; @@ -189,8 +188,7 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { for (Component child : this) { String componentCssString = getCss(child); if (componentCssString != null) { - getState().getChildCss().put(child.getConnectorId(), - componentCssString); + getState().getChildCss().put(child, componentCssString); } } -- 2.39.5