org.waveprotocol.wave.communication.gwt.JsonMessage.java Source code

Java tutorial

Introduction

Here is the source code for org.waveprotocol.wave.communication.gwt.JsonMessage.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.waveprotocol.wave.communication.gwt;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;

import org.waveprotocol.wave.communication.json.JsonException;
import org.waveprotocol.wave.communication.json.RawStringData;

/**
 * Implementation of a JSON message.
 * This is done by extending JavaScriptObject to minimise the size of the resulting code.
 *
 */
public class JsonMessage extends JavaScriptObject {
    private static final JsonSerializer serializer;
    private static boolean registerToString = false;

    static {
        if (GWT.isClient() && BrowserAidedJsonSerailizer.hasBrowserSupport()) {
            serializer = new BrowserAidedJsonSerailizer();
        } else {
            serializer = new JavascriptJsonSerializer();
        }
    }

    /**
     * Protected constructor. Instantiate via static create method.
     */
    protected JsonMessage() {
    }

    /**
     * @return a new empty JsonMessage.
     */
    public static JsonMessage createJsonMessage() {
        JsonMessage instance = JavaScriptObject.createObject().cast();
        registerNativeJsonMessageToString(instance);
        return instance;
    }

    /**
     * Delete all existing properties on this object.
     */
    public final native void clear() /*-{
                                     for (var p in this) {
                                     if (this.hasOwnProperty(p) && typeof this[p] != "function") {
                                     delete p;
                                     }
                                     }
                                     }-*/;

    /**
     * Copy the contents of an existing JsonMessage into this one.
     * @param message
     */
    public final native void copyFrom(JsonMessage message) /*-{
                                                           var clone = function (input) {
                                                           if (input === undefined || input === null) {
                                                           return null;
                                                           }
                                                           if (typeof input == 'object' && input.constructor === Array) {
                                                           var output = [];
                                                           for (var property = 0; property < input.length; ++property) {
                                                           output[property] = clone(input[property]);
                                                           }
                                                           return output;
                                                           }
                                                           if (typeof input == 'object') {
                                                           var output = {};
                                                           for (var property in input) {
                                                           if (input.hasOwnProperty(property)) {
                                                           output[property] = clone(input[property]);
                                                           }
                                                           }
                                                           return output;
                                                           }
                                                           return input;
                                                           };
                                                               
                                                           // delete any existing properties
                                                           for (var property in this) {
                                                           if (this.hasOwnProperty(property) && typeof this[property] != "function") {
                                                           delete property;
                                                           }
                                                           }
                                                               
                                                           // copy over new properties
                                                           for (var property in message) {
                                                           if (message.hasOwnProperty(property)) {
                                                           this[property] = clone(message[property]);
                                                           }
                                                           }
                                                           }-*/;

    /**
     * Convert this JsonMessage into a JSON String.
     * @return a JSON string representation.
     */
    public final String toJson() {
        return serializer.serialize(this);
    }

    public static <T extends JsonMessage> T parse(String json) throws JsonException {
        return createJsonMessage(json).<T>cast();
    }

    /**
     * Create a JsonMessage object from the given json
     * @param json The JSON String to load from.
     * @return true if evaluation is successful, false otherwise.
     */
    public static JsonMessage createJsonMessage(String json) throws JsonException {
        try {
            JsonMessage obj = (JsonMessage) serializer.parse(json);
            registerNativeJsonMessageToString(obj);
            return obj;
        } catch (JavaScriptException e) {
            throw new JsonException(e);
        }
    }

    /**
     * Create a JsonMessage object from the given json
     * @param json The JSON String to load from.
     * @return true if evaluation is successful, false otherwise.
     */
    public static JsonMessage createJsonMessage(RawStringData data) throws JsonException {
        try {
            JsonMessage obj = (JsonMessage) serializer.parse(data.getBaseString());
            JsonHelper.registerRawStringData(obj, data);
            registerNativeJsonMessageToString(obj);
            return obj;
        } catch (JavaScriptException e) {
            throw new JsonException(e);
        }
    }

    /**
     * JSON implementation of equals() since we can override it.
     *
     * TODO(user): Rename this to isEqualTo() once GWT compiler is fixed to
     * not crash when another interface defines this method and is implemented by a subclass
     * of JsonMessage.
     *
     * @return true if the other object is the same as this object.
     */
    public final native boolean nativeIsEqualTo(Object toCompare) /*-{
                                                                  var same = function (objectA, objectB) {
                                                                  if (typeof objectA == "object" && typeof objectB == "object") {
                                                                  // Check all A is in B
                                                                  for (var property in objectA) {
                                                                  if (objectA.hasOwnProperty(property) && typeof objectA[property] != "function") {
                                                                  if (!same(objectA[property], objectB[property])) {
                                                                  return false;
                                                                  }
                                                                  }
                                                                  }
                                                                      
                                                                  // Check all B is in A
                                                                  for (var property in objectB) {
                                                                  // Something in B we don't know in A.
                                                                  if (objectB.hasOwnProperty(property) && typeof objectB[property] != "function" &&
                                                                  !objectA.hasOwnProperty(property)) {
                                                                  return false;
                                                                  }
                                                                  }
                                                                  return true;
                                                                  } else  {
                                                                  return objectA == objectB;
                                                                  }
                                                                  };
                                                                      
                                                                  return same(this, toCompare);
                                                                  }-*/;

    /** Static version of toJson to allow us to call from JSNI */
    @SuppressWarnings("unused") // Called from JSNI
    private static final String jsonMessageToJson(JsonMessage instance) {
        return instance.toJson();
    }

    /** Enables toString on JSOs */
    public static void enableJsoToString() {
        registerToString = true;
    }

    /** Disables toString on JSOs */
    public static void disableJsoToString() {
        registerToString = false;
    }

    protected static final void registerNativeJsonMessageToString(JsonMessage instance) {
        if (registerToString) {
            nativeRegisterNativeJsonMessageToString(instance);
        }
    }

    /**
     * Recursively registers a native toString function on the object.
     * This toString method will be invoked from JavaScriptObject.toString(),
     * allowing us to print JSON when toString() is called on a JsonMessage.
     */
    private static final native void nativeRegisterNativeJsonMessageToString(JsonMessage instance)
    /*-{
      instance.toString = function () {
        return (
      @org.waveprotocol.wave.communication.gwt.JsonMessage::jsonMessageToJson(Lorg/waveprotocol/wave/communication/gwt/JsonMessage;)
          (this));
      }
        
      // set toString on all sub objects.
      for (var property in instance) {
        if (instance.hasOwnProperty(property) && typeof instance[property] == "object") {
    @org.waveprotocol.wave.communication.gwt.JsonMessage::registerNativeJsonMessageToString(Lorg/waveprotocol/wave/communication/gwt/JsonMessage;)
        (instance[property]);
        }
      }
    }-*/;
}