Class ObjectResolver

java.lang.Object
com.cedarsoftware.util.io.Resolver
com.cedarsoftware.util.io.ObjectResolver
All Implemented Interfaces:
ReaderContext

public class ObjectResolver extends Resolver

The ObjectResolver converts the raw Maps created from the JsonParser to Java objects (a graph of Java instances). The Maps have an optional type entry associated to them to indicate what Java peer instance to create. The reason type is optional is because it can be inferred in a couple instances. A non-primitive field that points to an object that is of the same type of the field, does not require the '@type' because it can be inferred from the field. This is not always the case. For example, if a Person field points to an Employee object (where Employee is a subclass of Person), then the resolver cannot create an instance of the field type (Person) because this is not the proper type. (It had an Employee record with more fields in this example). In this case, the writer recognizes that the instance type and field type are not the same and therefore it writes the @type.

A similar case as above occurs with specific array types. If there is a Person[] containing Person and Employee instances, then the Person instances will not have the '@type' but the employee instances will (because they are more derived than Person).

The resolver 'wires' the original object graph. It does this by replacing '@ref' values in the Maps with pointers (on the field of the associated instance of the Map) to the object that has the same ID. If the object has not yet been read, then an UnresolvedReference is created. These are back-patched at the end of the resolution process. UnresolvedReference keeps track of what field or array element the actual value should be stored within, and then locates the object (by id), and updates the appropriate value.

Author:
John DeRegnaucourt ([email protected])
Copyright (c) Cedar Software LLC

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

License

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.
  • Constructor Details

    • ObjectResolver

      protected ObjectResolver(ReadOptions readOptions, ReferenceTracker references, com.cedarsoftware.util.convert.Converter converter)
      Constructor
      Parameters:
      readOptions - Options to use while reading.
  • Method Details

    • traverseFields

      public void traverseFields(Deque<JsonObject> stack, JsonObject jsonObj)
      Walk the Java object fields and copy them from the JSON object to the Java object, performing any necessary conversions on primitives, or deep traversals for field assignments to other objects, arrays, Collections, or Maps.
      Parameters:
      stack - Stack (Deque) used for graph traversal.
      jsonObj - a Map-of-Map representation of the current object being examined (containing all fields).
    • assignField

      protected void assignField(Deque<JsonObject> stack, JsonObject jsonObj, Injector injector, Object rhs)
      Map Json Map object field to Java object field.
      Parameters:
      stack - Stack (Deque) used for graph traversal.
      jsonObj - a Map-of-Map representation of the current object being examined (containing all fields).
      injector - instance of injector used for setting values on the object.
      rhs - the JSON value that will be converted and stored in the 'field' on the associated Java target object.
    • handleMissingField

      protected void handleMissingField(Deque<JsonObject> stack, JsonObject jsonObj, Object rhs, String missingField)
      Try to create a java object from the missing field. Mostly primitive types and jsonObject that contains @type attribute will be candidate for the missing field callback, others will be ignored. All missing field are stored for later notification
      Parameters:
      stack - Stack (Deque) used for graph traversal.
      jsonObj - a Map-of-Map representation of the current object being examined (containing all fields).
      rhs - the JSON value that will be converted and stored in the 'field' on the associated Java target object.
      missingField - name of the missing field in the java object.
    • traverseCollection

      protected void traverseCollection(Deque<JsonObject> stack, JsonObject jsonObj)
      Process java.util.Collection and it's derivatives. Collections are written specially so that the serialization does not expose the Collection's internal structure, for example, a TreeSet. All entries are processed, except unresolved references, which are filled in later. For an index-able collection, the unresolved references are set back into the proper element location. For non-index-able collections (Sets), the unresolved references are added via .add().
      Specified by:
      traverseCollection in class Resolver
      Parameters:
      jsonObj - a Map-of-Map representation of the JSON input stream.
    • reconcileCollection

      public static void reconcileCollection(JsonObject jsonObj, Collection col)
    • traverseArray

      protected void traverseArray(Deque<JsonObject> stack, JsonObject jsonObj)
      Traverse the JsonObject associated to an array (of any type). Convert and assign the list of items in the JsonObject (stored in the @items field) to each array element. All array elements are processed excluding elements that reference an unresolved object. These are filled in later.
      Specified by:
      traverseArray in class Resolver
      Parameters:
      stack - a Stack (Deque) used to support graph traversal.
      jsonObj - a Map-of-Map representation of the JSON input stream.
    • readWithFactoryIfExists

      protected Object readWithFactoryIfExists(Object o, Class inferredType, Deque<JsonObject> stack)
      Convert the passed in object (o) to a proper Java object. If the passed in object (o) has a custom reader associated to it, then have it convert the object. If there is no custom reader, then return null.
      Specified by:
      readWithFactoryIfExists in class Resolver
      Parameters:
      o - Object to read (convert). Will be either a JsonObject or a JSON primitive String, long, boolean, double, or null.
      inferredType - Class destination type to which the passed in object should be converted to.
      stack - a Stack (Deque) used to support graph traversal.
      Returns:
      Java object converted from the passed in object o, or if there is no custom reader.
    • getRawType

      public static Class getRawType(Type t)
      Given the passed in Type t, return the raw type of it, if the passed in value is a ParameterizedType.
      Parameters:
      t - Type to attempt to get raw type from.
      Returns:
      Raw type obtained from the passed in parameterized type or null if T is not a ParameterizedType