| /* | 
|  * Copyright (C) 2008 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 cn.emay.sdk.util.json.gson; | 
|   | 
| import static cn.emay.sdk.util.json.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS; | 
| import static cn.emay.sdk.util.json.gson.Gson.DEFAULT_ESCAPE_HTML; | 
| import static cn.emay.sdk.util.json.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE; | 
| import static cn.emay.sdk.util.json.gson.Gson.DEFAULT_LENIENT; | 
| import static cn.emay.sdk.util.json.gson.Gson.DEFAULT_PRETTY_PRINT; | 
| import static cn.emay.sdk.util.json.gson.Gson.DEFAULT_SERIALIZE_NULLS; | 
| import static cn.emay.sdk.util.json.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES; | 
|   | 
| import java.lang.reflect.Type; | 
| import java.sql.Timestamp; | 
| import java.text.DateFormat; | 
| import java.util.ArrayList; | 
| import java.util.Collections; | 
| import java.util.Date; | 
| import java.util.HashMap; | 
| import java.util.List; | 
| import java.util.Map; | 
|   | 
| import cn.emay.sdk.util.json.gson.internal.$Gson$Preconditions; | 
| import cn.emay.sdk.util.json.gson.internal.Excluder; | 
| import cn.emay.sdk.util.json.gson.internal.bind.TypeAdapters; | 
| import cn.emay.sdk.util.json.gson.reflect.TypeToken; | 
| import cn.emay.sdk.util.json.gson.stream.JsonReader; | 
|   | 
| /** | 
|  * <p> | 
|  * Use this builder to construct a {@link Gson} instance when you need to set | 
|  * configuration options other than the default. For {@link Gson} with default | 
|  * configuration, it is simpler to use {@code new Gson()}. {@code GsonBuilder} | 
|  * is best used by creating it, and then invoking its various configuration | 
|  * methods, and finally calling create. | 
|  * </p> | 
|  * | 
|  * <p> | 
|  * The following is an example shows how to use the {@code GsonBuilder} to | 
|  * construct a Gson instance: | 
|  * | 
|  * <pre> | 
|  * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdTypeAdapter()).enableComplexMapKeySerialization().serializeNulls().setDateFormat(DateFormat.LONG) | 
|  *         .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting().setVersion(1.0).create(); | 
|  * </pre> | 
|  * </p> | 
|  * | 
|  * <p> | 
|  * NOTES: | 
|  * <ul> | 
|  * <li>the order of invocation of configuration methods does not matter.</li> | 
|  * <li>The default serialization of {@link Date} and its subclasses in Gson does | 
|  * not contain time-zone information. So, if you are using date/time instances, | 
|  * use {@code GsonBuilder} and its {@code setDateFormat} methods.</li> | 
|  * </ul> | 
|  * </p> | 
|  * | 
|  * @author Inderjeet Singh | 
|  * @author Joel Leitch | 
|  * @author Jesse Wilson | 
|  */ | 
| public final class GsonBuilder { | 
|     private Excluder excluder = Excluder.DEFAULT; | 
|     private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT; | 
|     private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY; | 
|     private final Map<Type, InstanceCreator<?>> instanceCreators = new HashMap<Type, InstanceCreator<?>>(); | 
|     private final List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(); | 
|     /** | 
|      * tree-style hierarchy factories. These come after factories for backwards | 
|      * compatibility. | 
|      */ | 
|     private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>(); | 
|     private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; | 
|     private String datePattern; | 
|     private int dateStyle = DateFormat.DEFAULT; | 
|     private int timeStyle = DateFormat.DEFAULT; | 
|     private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; | 
|     private boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES; | 
|     private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML; | 
|     private boolean prettyPrinting = DEFAULT_PRETTY_PRINT; | 
|     private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE; | 
|     private boolean lenient = DEFAULT_LENIENT; | 
|   | 
|     /** | 
|      * Creates a GsonBuilder instance that can be used to build Gson with various | 
|      * configuration settings. GsonBuilder follows the builder pattern, and it is | 
|      * typically used by first invoking various configuration methods to set desired | 
|      * options, and finally calling {@link #create()}. | 
|      */ | 
|     public GsonBuilder() { | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to enable versioning support. | 
|      * | 
|      * @param ignoreVersionsAfter | 
|      *            any field or type marked with a version higher than this value are | 
|      *            ignored during serialization or deserialization. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      */ | 
|     public GsonBuilder setVersion(double ignoreVersionsAfter) { | 
|         excluder = excluder.withVersion(ignoreVersionsAfter); | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to excludes all class fields that have the specified | 
|      * modifiers. By default, Gson will exclude all fields marked transient or | 
|      * static. This method will override that behavior. | 
|      * | 
|      * @param modifiers | 
|      *            the field modifiers. You must use the modifiers specified in the | 
|      *            {@link java.lang.reflect.Modifier} class. For example, | 
|      *            {@link java.lang.reflect.Modifier#TRANSIENT}, | 
|      *            {@link java.lang.reflect.Modifier#STATIC}. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      */ | 
|     public GsonBuilder excludeFieldsWithModifiers(int... modifiers) { | 
|         excluder = excluder.withModifiers(modifiers); | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Makes the output JSON non-executable in Javascript by prefixing the generated | 
|      * JSON with some special text. This prevents attacks from third-party sites | 
|      * through script sourcing. See | 
|      * <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue | 
|      * 42</a> for details. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.3 | 
|      */ | 
|     public GsonBuilder generateNonExecutableJson() { | 
|         this.generateNonExecutableJson = true; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to exclude all fields from consideration for serialization or | 
|      * deserialization that do not have the | 
|      * {@link com.google.gson.annotations.Expose} annotation. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      */ | 
|     public GsonBuilder excludeFieldsWithoutExposeAnnotation() { | 
|         excluder = excluder.excludeFieldsWithoutExposeAnnotation(); | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configure Gson to serialize null fields. By default, Gson omits all fields | 
|      * that are null during serialization. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.2 | 
|      */ | 
|     public GsonBuilder serializeNulls() { | 
|         this.serializeNulls = true; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Enabling this feature will only change the serialized form if the map key is | 
|      * a complex type (i.e. non-primitive) in its <strong>serialized</strong> JSON | 
|      * form. The default implementation of map serialization uses {@code toString()} | 
|      * on the key; however, when this is called then one of the following cases | 
|      * apply: | 
|      * | 
|      * <h3>Maps as JSON objects</h3> For this case, assume that a type adapter is | 
|      * registered to serialize and deserialize some {@code Point} class, which | 
|      * contains an x and y coordinate, to/from the JSON Primitive string value | 
|      * {@code "(x,y)"}. The Java map would then be serialized as a | 
|      * {@link JsonObject}. | 
|      * | 
|      * <p> | 
|      * Below is an example: | 
|      *  | 
|      * <pre> | 
|      * { | 
|      *     @code | 
|      *     Gson gson = new GsonBuilder().register(Point.class, new MyPointTypeAdapter()).enableComplexMapKeySerialization().create(); | 
|      * | 
|      *     Map<Point, String> original = new LinkedHashMap<Point, String>(); | 
|      *     original.put(new Point(5, 6), "a"); | 
|      *     original.put(new Point(8, 8), "b"); | 
|      *     System.out.println(gson.toJson(original, type)); | 
|      * } | 
|      * </pre> | 
|      *  | 
|      * The above code prints this JSON object: | 
|      *  | 
|      * <pre> | 
|      *   {@code | 
|      *   { | 
|      *     "(5,6)": "a", | 
|      *     "(8,8)": "b" | 
|      *   } | 
|      * } | 
|      * </pre> | 
|      * | 
|      * <h3>Maps as JSON arrays</h3> For this case, assume that a type adapter was | 
|      * NOT registered for some {@code Point} class, but rather the default Gson | 
|      * serialization is applied. In this case, some {@code new Point(2,3)} would | 
|      * serialize as {@code {"x":2,"y":5}}. | 
|      * | 
|      * <p> | 
|      * Given the assumption above, a {@code Map<Point, String>} will be serialize as | 
|      * an array of arrays (can be viewed as an entry set of pairs). | 
|      * | 
|      * <p> | 
|      * Below is an example of serializing complex types as JSON arrays: | 
|      *  | 
|      * <pre> | 
|      *  {@code | 
|      *   Gson gson = new GsonBuilder() | 
|      *       .enableComplexMapKeySerialization() | 
|      *       .create(); | 
|      * | 
|      *   Map<Point, String> original = new LinkedHashMap<Point, String>(); | 
|      *   original.put(new Point(5, 6), "a"); | 
|      *   original.put(new Point(8, 8), "b"); | 
|      *   System.out.println(gson.toJson(original, type)); | 
|      * } | 
|      * | 
|      * The JSON output would look as follows: | 
|      * <pre>   {@code | 
|      *   [ | 
|      *     [ | 
|      *       { | 
|      *         "x": 5, | 
|      *         "y": 6 | 
|      *       }, | 
|      *       "a" | 
|      *     ], | 
|      *     [ | 
|      *       { | 
|      *         "x": 8, | 
|      *         "y": 8 | 
|      *       }, | 
|      *       "b" | 
|      *     ] | 
|      *   ] | 
|      * } | 
|      * </pre> | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.7 | 
|      */ | 
|     public GsonBuilder enableComplexMapKeySerialization() { | 
|         complexMapKeySerialization = true; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to exclude inner classes during serialization. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.3 | 
|      */ | 
|     public GsonBuilder disableInnerClassSerialization() { | 
|         excluder = excluder.disableInnerClassSerialization(); | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to apply a specific serialization policy for {@code Long} and | 
|      * {@code long} objects. | 
|      * | 
|      * @param serializationPolicy | 
|      *            the particular policy to use for serializing longs. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.3 | 
|      */ | 
|     public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) { | 
|         this.longSerializationPolicy = serializationPolicy; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to apply a specific naming policy to an object's field during | 
|      * serialization and deserialization. | 
|      * | 
|      * @param namingConvention | 
|      *            the JSON field naming convention to use for serialization and | 
|      *            deserialization. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      */ | 
|     public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) { | 
|         this.fieldNamingPolicy = namingConvention; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to apply a specific naming policy strategy to an object's | 
|      * field during serialization and deserialization. | 
|      * | 
|      * @param fieldNamingStrategy | 
|      *            the actual naming strategy to apply to the fields | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.3 | 
|      */ | 
|     public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) { | 
|         this.fieldNamingPolicy = fieldNamingStrategy; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to apply a set of exclusion strategies during both | 
|      * serialization and deserialization. Each of the {@code strategies} will be | 
|      * applied as a disjunction rule. This means that if one of the | 
|      * {@code strategies} suggests that a field (or class) should be skipped then | 
|      * that field (or object) is skipped during serialization/deserialization. | 
|      * | 
|      * @param strategies | 
|      *            the set of strategy object to apply during object | 
|      *            (de)serialization. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.4 | 
|      */ | 
|     public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) { | 
|         for (ExclusionStrategy strategy : strategies) { | 
|             excluder = excluder.withExclusionStrategy(strategy, true, true); | 
|         } | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to apply the passed in exclusion strategy during | 
|      * serialization. If this method is invoked numerous times with different | 
|      * exclusion strategy objects then the exclusion strategies that were added will | 
|      * be applied as a disjunction rule. This means that if one of the added | 
|      * exclusion strategies suggests that a field (or class) should be skipped then | 
|      * that field (or object) is skipped during its serialization. | 
|      * | 
|      * @param strategy | 
|      *            an exclusion strategy to apply during serialization. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.7 | 
|      */ | 
|     public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) { | 
|         excluder = excluder.withExclusionStrategy(strategy, true, false); | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to apply the passed in exclusion strategy during | 
|      * deserialization. If this method is invoked numerous times with different | 
|      * exclusion strategy objects then the exclusion strategies that were added will | 
|      * be applied as a disjunction rule. This means that if one of the added | 
|      * exclusion strategies suggests that a field (or class) should be skipped then | 
|      * that field (or object) is skipped during its deserialization. | 
|      * | 
|      * @param strategy | 
|      *            an exclusion strategy to apply during deserialization. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.7 | 
|      */ | 
|     public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) { | 
|         excluder = excluder.withExclusionStrategy(strategy, false, true); | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to output Json that fits in a page for pretty printing. This | 
|      * option only affects Json serialization. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      */ | 
|     public GsonBuilder setPrettyPrinting() { | 
|         prettyPrinting = true; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * By default, Gson is strict and only accepts JSON as specified by | 
|      * <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. This option makes | 
|      * the parser liberal in what it accepts. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @see JsonReader#setLenient(boolean) | 
|      */ | 
|     public GsonBuilder setLenient() { | 
|         lenient = true; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * By default, Gson escapes HTML characters such as < > etc. Use this | 
|      * option to configure Gson to pass-through HTML characters as is. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.3 | 
|      */ | 
|     public GsonBuilder disableHtmlEscaping() { | 
|         this.escapeHtmlChars = false; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to serialize {@code Date} objects according to the pattern | 
|      * provided. You can call this method or {@link #setDateFormat(int)} multiple | 
|      * times, but only the last invocation will be used to decide the serialization | 
|      * format. | 
|      * | 
|      * <p> | 
|      * The date format will be used to serialize and deserialize | 
|      * {@link java.util.Date}, {@link java.sql.Timestamp} and {@link java.sql.Date}. | 
|      * | 
|      * <p> | 
|      * Note that this pattern must abide by the convention provided by | 
|      * {@code SimpleDateFormat} class. See the documentation in | 
|      * {@link java.text.SimpleDateFormat} for more information on valid date and | 
|      * time patterns. | 
|      * </p> | 
|      * | 
|      * @param pattern | 
|      *            the pattern that dates will be serialized/deserialized to/from | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.2 | 
|      */ | 
|     public GsonBuilder setDateFormat(String pattern) { | 
|         // TODO(Joel): Make this fail fast if it is an invalid date format | 
|         this.datePattern = pattern; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to to serialize {@code Date} objects according to the style | 
|      * value provided. You can call this method or {@link #setDateFormat(String)} | 
|      * multiple times, but only the last invocation will be used to decide the | 
|      * serialization format. | 
|      * | 
|      * <p> | 
|      * Note that this style value should be one of the predefined constants in the | 
|      * {@code DateFormat} class. See the documentation in | 
|      * {@link java.text.DateFormat} for more information on the valid style | 
|      * constants. | 
|      * </p> | 
|      * | 
|      * @param style | 
|      *            the predefined date style that date objects will be | 
|      *            serialized/deserialized to/from | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.2 | 
|      */ | 
|     public GsonBuilder setDateFormat(int style) { | 
|         this.dateStyle = style; | 
|         this.datePattern = null; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson to to serialize {@code Date} objects according to the style | 
|      * value provided. You can call this method or {@link #setDateFormat(String)} | 
|      * multiple times, but only the last invocation will be used to decide the | 
|      * serialization format. | 
|      * | 
|      * <p> | 
|      * Note that this style value should be one of the predefined constants in the | 
|      * {@code DateFormat} class. See the documentation in | 
|      * {@link java.text.DateFormat} for more information on the valid style | 
|      * constants. | 
|      * </p> | 
|      * | 
|      * @param dateStyle | 
|      *            the predefined date style that date objects will be | 
|      *            serialized/deserialized to/from | 
|      * @param timeStyle | 
|      *            the predefined style for the time portion of the date objects | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.2 | 
|      */ | 
|     public GsonBuilder setDateFormat(int dateStyle, int timeStyle) { | 
|         this.dateStyle = dateStyle; | 
|         this.timeStyle = timeStyle; | 
|         this.datePattern = null; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson for custom serialization or deserialization. This method | 
|      * combines the registration of an {@link TypeAdapter}, {@link InstanceCreator}, | 
|      * {@link JsonSerializer}, and a {@link JsonDeserializer}. It is best used when | 
|      * a single object {@code typeAdapter} implements all the required interfaces | 
|      * for custom serialization with Gson. If a type adapter was previously | 
|      * registered for the specified {@code type}, it is overwritten. | 
|      * | 
|      * <p> | 
|      * This registers the type specified and no other types: you must manually | 
|      * register related types! For example, applications registering | 
|      * {@code boolean.class} should also register {@code | 
|      * Boolean.class}. | 
|      * | 
|      * @param type | 
|      *            the type definition for the type adapter being registered | 
|      * @param typeAdapter | 
|      *            This object must implement at least one of the | 
|      *            {@link TypeAdapter}, {@link InstanceCreator}, | 
|      *            {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      */ | 
|     @SuppressWarnings({ "unchecked", "rawtypes" }) | 
|     public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) { | 
|         $Gson$Preconditions.checkArgument( | 
|                 typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?> || typeAdapter instanceof TypeAdapter<?>); | 
|         if (typeAdapter instanceof InstanceCreator<?>) { | 
|             instanceCreators.put(type, (InstanceCreator) typeAdapter); | 
|         } | 
|         if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) { | 
|             TypeToken<?> typeToken = TypeToken.get(type); | 
|             factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter)); | 
|         } | 
|         if (typeAdapter instanceof TypeAdapter<?>) { | 
|             factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter) typeAdapter)); | 
|         } | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Register a factory for type adapters. Registering a factory is useful when | 
|      * the type adapter needs to be configured based on the type of the field being | 
|      * processed. Gson is designed to handle a large number of factories, so you | 
|      * should consider registering them to be at par with registering an individual | 
|      * type adapter. | 
|      * | 
|      * @since 2.1 | 
|      */ | 
|     public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) { | 
|         factories.add(factory); | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Configures Gson for custom serialization or deserialization for an | 
|      * inheritance type hierarchy. This method combines the registration of a | 
|      * {@link TypeAdapter}, {@link JsonSerializer} and a {@link JsonDeserializer}. | 
|      * If a type adapter was previously registered for the specified type hierarchy, | 
|      * it is overridden. If a type adapter is registered for a specific type in the | 
|      * type hierarchy, it will be invoked instead of the one registered for the type | 
|      * hierarchy. | 
|      * | 
|      * @param baseType | 
|      *            the class definition for the type adapter being registered for the | 
|      *            base class or interface | 
|      * @param typeAdapter | 
|      *            This object must implement at least one of {@link TypeAdapter}, | 
|      *            {@link JsonSerializer} or {@link JsonDeserializer} interfaces. | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.7 | 
|      */ | 
|     @SuppressWarnings({ "unchecked", "rawtypes" }) | 
|     public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) { | 
|         $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof TypeAdapter<?>); | 
|         if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) { | 
|             hierarchyFactories.add(0, TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter)); | 
|         } | 
|         if (typeAdapter instanceof TypeAdapter<?>) { | 
|             factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter) typeAdapter)); | 
|         } | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON | 
|      * specification</a> disallows special double values (NaN, Infinity, -Infinity). | 
|      * However, <a href= | 
|      * "http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript | 
|      * specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as | 
|      * valid Javascript values. Moreover, most JavaScript engines will accept these | 
|      * special values in JSON without problem. So, at a practical level, it makes | 
|      * sense to accept these values as valid JSON even though JSON specification | 
|      * disallows them. | 
|      * | 
|      * <p> | 
|      * Gson always accepts these special values during deserialization. However, it | 
|      * outputs strictly compliant JSON. Hence, if it encounters a float value | 
|      * {@link Float#NaN}, {@link Float#POSITIVE_INFINITY}, | 
|      * {@link Float#NEGATIVE_INFINITY}, or a double value {@link Double#NaN}, | 
|      * {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it will | 
|      * throw an {@link IllegalArgumentException}. This method provides a way to | 
|      * override the default behavior when you know that the JSON receiver will be | 
|      * able to handle these special values. | 
|      * | 
|      * @return a reference to this {@code GsonBuilder} object to fulfill the | 
|      *         "Builder" pattern | 
|      * @since 1.3 | 
|      */ | 
|     public GsonBuilder serializeSpecialFloatingPointValues() { | 
|         this.serializeSpecialFloatingPointValues = true; | 
|         return this; | 
|     } | 
|   | 
|     /** | 
|      * Creates a {@link Gson} instance based on the current configuration. This | 
|      * method is free of side-effects to this {@code GsonBuilder} instance and hence | 
|      * can be called multiple times. | 
|      * | 
|      * @return an instance of Gson configured with the options currently set in this | 
|      *         builder | 
|      */ | 
|     public Gson create() { | 
|         List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(); | 
|         factories.addAll(this.factories); | 
|         Collections.reverse(factories); | 
|         factories.addAll(this.hierarchyFactories); | 
|         addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories); | 
|   | 
|         return new Gson(excluder, fieldNamingPolicy, instanceCreators, serializeNulls, complexMapKeySerialization, generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient, | 
|                 serializeSpecialFloatingPointValues, longSerializationPolicy, factories); | 
|     } | 
|   | 
|     private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, List<TypeAdapterFactory> factories) { | 
|         DefaultDateTypeAdapter dateTypeAdapter; | 
|         if (datePattern != null && !"".equals(datePattern.trim())) { | 
|             dateTypeAdapter = new DefaultDateTypeAdapter(datePattern); | 
|         } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) { | 
|             dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle); | 
|         } else { | 
|             return; | 
|         } | 
|   | 
|         factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter)); | 
|         factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter)); | 
|         factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter)); | 
|     } | 
| } |