gt:         JSONNull asNull = jsonValue.isNull();
context: /*
   * WBI Indicator Explorer
   *
   * Copyright 2015 Sebastian Nogara <snogaraleal@gmail.com>
   *
   * This file is part of WBI.
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package rpc.client.data;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import com.google.gwt.json.client.JSONArray;
  import com.google.gwt.json.client.JSONBoolean;
  import com.google.gwt.json.client.JSONNull;
  import com.google.gwt.json.client.JSONNumber;
  import com.google.gwt.json.client.JSONObject;
  import com.google.gwt.json.client.JSONParser;
  import com.google.gwt.json.client.JSONString;
  import com.google.gwt.json.client.JSONValue;
  
  import rpc.shared.data.Serializable;
  import rpc.shared.data.Serializer;
  import rpc.shared.data.SerializerException;
  import rpc.shared.data.Type;
  import rpc.shared.data.Utils;
  import rpc.shared.data.factory.NoSuitableSerializableFactory;
  import rpc.shared.data.factory.SerializableFactoryProvider;
  
  /**
   * Client-side JSON {@link Serializer}.
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public class JSONSerializer implements Serializer {
      private SerializableFactoryProvider provider;
  
      /**
       * Initialize {@code JSONSerializer}.
       */
      public JSONSerializer() {}
  
      /**
       * Initialize {@code JSONSerializer}.
       *
       * @param provider Provider of {@code Serializable} object instances.
       */
      public JSONSerializer(SerializableFactoryProvider provider) {
          this.provider = provider;
      }
  
      /**
       * Produce a {@code JSONValue} from the specified {@code Object}.
       *
       * @param object {@code Object}.
       * @return {@code JSONValue}.
       */
      private JSONValue toJSONValue(Object object) {
          // Null
          if (object == null) {
              return JSONNull.getInstance();
          }
  
          // Boolean
          Boolean asBoolean = Utils.isBoolean(object);
          if (asBoolean != null) {
              return JSONBoolean.getInstance(asBoolean);
          }
  
          // Integer
          Integer asInteger = Utils.isInteger(object);
          if (asInteger != null) {
              return new JSONNumber(asInteger);
          }
  
          // Long
          Long asLong = Utils.isLong(object);
          if (asLong != null) {
              return new JSONNumber(asLong);
          }
  
          // Float
          Float asFloat = Utils.isFloat(object);
          if (asFloat != null) {
              return new JSONNumber(asFloat);
          }
  
          // Double
          Double asDouble = Utils.isDouble(object);
          if (asDouble != null) {
              return new JSONNumber(asDouble);
          }
  
          // String
          String asString = Utils.isString(object);
          if (asString != null) {
              return new JSONString(asString);
          }
  
          // Enum
          Enum asEnum = Utils.isEnum(object);
          if (asEnum != null) {
              return new JSONString(asEnum.toString());
          }
  
          // Serializable
          Serializable asSerializable = Utils.isSerializable(object);
          if (asSerializable != null) {
              JSONObject jsonObject = new JSONObject();
  
              for (String field : asSerializable.fields().keySet()) {
                  Object value = asSerializable.get(field);
                  jsonObject.put(field, toJSONValue(value));
              }
  
              return jsonObject;
          }
  
          // List
          List<Object> asSerializableList = Utils.isSerializableList(object);
          if (asSerializableList != null) {
              JSONArray jsonArray = new JSONArray();
  
              for (int i = 0; i < asSerializableList.size(); i++) {
                  Object item = asSerializableList.get(i);
                  jsonArray.set(i, toJSONValue(item));
              }
  
              return jsonArray;
          }
  
          // Map
          Map<Object, Object> asSerializableMap =
              Utils.isSerializableMap(object);
          if (asSerializableMap != null) {
              JSONObject jsonObject = new JSONObject();
  
              for (Map.Entry<Object, Object> entry :
                      asSerializableMap.entrySet()) {
  
                  Object keyObject = entry.getKey();
                  Object valueObject = entry.getValue();
  
                  String key = null;
  
                  String keyAsString = Utils.isString(keyObject);
                  if (keyAsString != null) {
                      key = keyAsString;
                  }
  
                  Enum keyAsEnum = Utils.isEnum(keyObject);
                  if (keyAsEnum != null) {
                      key = keyAsEnum.toString();
                  }
  
                  jsonObject.put(key, toJSONValue(valueObject));
              }
  
              return jsonObject;
          }
  
          return null;
      }
  
      @Override
      public String serialize(Object object) throws SerializerException {
          if (!Utils.isSerializationCapable(object)) {
              throw new SerializerException(
                  SerializerException.Error.NOT_SERIALIZABLE);
          }
  
          JSONValue jsonValue = toJSONValue(object);
  
          if (jsonValue == null) {
              throw new SerializerException(
                  SerializerException.Error.NOT_SERIALIZABLE);
          }
  
          return jsonValue.toString();
      }
  
      /**
       * Produce a new {@code Object} instance from the specified
       * {@code JSONValue}.
       *
       * @param jsonValue {@code JSONValue}.
       * @param expected Expected object {@link Type}.
       * @return New {@code Object}.
       * @throws NoSuitableSerializableFactory
       */
      private Object fromJSONValue(JSONValue jsonValue, Type expected)
          throws NoSuitableSerializableFactory {
  
          if (jsonValue == null) {
              return null;
          }
  
          // Null
  