| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.requestfactory.client.impl; |
| |
| import com.google.gwt.core.client.JavaScriptObject; |
| import com.google.gwt.core.client.JsArray; |
| import com.google.gwt.core.client.JsArrayString; |
| import com.google.gwt.requestfactory.shared.EntityProxy; |
| import com.google.gwt.requestfactory.shared.EntityProxyId; |
| import com.google.gwt.requestfactory.shared.ValueCodex; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| /** |
| * Analogous to {@link ValueCodex}, but for object types. |
| */ |
| public class EntityCodex { |
| /** |
| * Collection support is limited to value types and resolving ids. |
| */ |
| public static Object decode(Class<?> type, Class<?> elementType, |
| final AbstractRequestContext requestContext, Object jso) { |
| if (jso == null) { |
| return null; |
| } |
| |
| // Collection support |
| if (elementType != null) { |
| Collection<Object> collection = null; |
| if (List.class == type) { |
| collection = new ArrayList<Object>(); |
| } else if (Set.class == type) { |
| collection = new HashSet<Object>(); |
| } |
| |
| // OK, here's a Java typesystem wart, we need an JsAny type |
| if (ValueCodex.canDecode(elementType)) { |
| @SuppressWarnings("unchecked") |
| JsArray<JavaScriptObject> array = (JsArray<JavaScriptObject>) jso; |
| for (int i = 0, j = array.length(); i < j; i++) { |
| if (isNull(array, i)) { |
| collection.add(null); |
| } else { |
| // Use getString() to make DevMode not complain about primitives |
| Object element = ValueCodex.convertFromString(elementType, |
| getString(array, i)); |
| collection.add(element); |
| } |
| } |
| } else { |
| JsArrayString array = (JsArrayString) jso; |
| for (int i = 0, j = array.length(); i < j; i++) { |
| Object element = decode(elementType, null, requestContext, |
| array.get(i)); |
| collection.add(element); |
| } |
| } |
| return collection; |
| } |
| |
| // Really want EntityProxy.isAssignableFrom(type) |
| if (requestContext.getRequestFactory().getTypeToken(type) != null) { |
| EntityProxyId<?> id = requestContext.getRequestFactory().getProxyId( |
| (String) jso); |
| return requestContext.getProxyForReturnPayloadGraph( |
| (SimpleEntityProxyId<?>) id).as(); |
| } |
| |
| // Fall back to values |
| return ValueCodex.convertFromString(type, String.valueOf(jso)); |
| } |
| |
| /** |
| * Create a wire-format representation of an object. |
| */ |
| public static String encodeForJsonPayload(Object value) { |
| if (value == null) { |
| return "null"; |
| } |
| |
| if (value instanceof Iterable<?>) { |
| StringBuffer toReturn = new StringBuffer(); |
| toReturn.append('['); |
| boolean first = true; |
| for (Object val : ((Iterable<?>) value)) { |
| if (!first) { |
| toReturn.append(','); |
| } else { |
| first = false; |
| } |
| toReturn.append(encodeForJsonPayload(val)); |
| } |
| toReturn.append(']'); |
| return toReturn.toString(); |
| } |
| |
| if (value instanceof EntityProxy) { |
| String historyToken = AbstractRequestFactory.getHistoryToken((EntityProxy) value); |
| return "\"" + historyToken + "\""; |
| } |
| |
| return ValueCodex.encodeForJsonPayload(value); |
| } |
| |
| private static native String getString(JavaScriptObject array, int index) /*-{ |
| return String(array[index]); |
| }-*/; |
| |
| /** |
| * Looks for an explicit null value. |
| */ |
| private static native boolean isNull(JavaScriptObject array, int index) /*-{ |
| return array[index] === null; |
| }-*/; |
| } |