Class JsonToDataConverter


  • public class JsonToDataConverter
    extends Object
    Converts json data to Openbravo business object(s). This class can translate single a BaseOBObject as well as lists of BaseOBObject instances. A single JSONObject is assumed to represent one BaseOBObject. The conversion process goes through the following steps for each JSONObject. First it is checked if the JSONObject has an id and entityName value. If so the logic tries to find the object in the internal key-to-object map (maintained during the conversion). If not found then the database is search. if not found there then a new BaseOBObject is created.If the object has an id then it is put in the key-to-object map so that it can be found if later objects refer to it.

    Then the next step is to convert/set the values. the logic walks through the properties of the object (the properties are defined by the entity of the object (see BaseOBObject.getEntity() and Entity.getProperties(). For primitive values, the property name (Property.getName()) is used to search a value in the JSONObject. The value is retrieved converted and then set in the business object.

    Reference/foreign key properties are handled differently. In this case the property name is appended with the ".id" postfix and this name is used to search for a value in the JSONObject. If there is no such value present then the property name is used. The id value is used to search in the key-to-object map and in the database (in this order). If not found then a new object is created as it may be present later in the overall json string. The system later tracks that there are no such maverick objects present (call getErrors() to check this).

    This class also handles a special type of property/keys. It can handle setting values in related objects also. For example say that the json object represents a sales order and has these keys (and their values):

    • businessPartner.paymentTerm.name
    • businessPartner.paymentTerm.id
    • businessPartner.id
    Then these keys are used to:
    • set the businesspartner object in the sales order using the businesspartner.id
    • set the paymentTerm in the business partner using the businessPartner.paymentTerm.id
    • set the name of the paymentTerm using the businessPartner.paymentTerm.name
    So this class can handle flat JSON structures which represent a hierarchy/path in their name. NOTE:
    • This class holds state during the conversion process. It can not be shared by multiple threads.
    • After calling one of the toBaseOBObject* methods the conversion errors can be retrieved using the getErrors() method.
    • When calling toBaseOBObject* multiple times you can clear the internal state by calling clearState().
    Author:
    mtaal
    • Constructor Detail

      • JsonToDataConverter

        public JsonToDataConverter()
    • Method Detail

      • convertJsonToPropertyValue

        public static Object convertJsonToPropertyValue​(Property property,
                                                        Object value)
        Gets a value from json and converts it to a valid value for the DAL.
      • clearState

        public void clearState()
      • toBaseOBObjects

        public List<BaseOBObject> toBaseOBObjects​(org.codehaus.jettison.json.JSONArray jsonArray)
        Converts a JSONArray to a list of BaseOBObject instances. The JSONArray is assumed to contain only JSONObjects which represent each a BaseOBObject. See the conversion logic description in the class header for more information.
        Parameters:
        jsonArray - the array with JSONObjects
        Returns:
        the list of BaseOBObjects.
      • toBaseOBObjects

        public List<BaseOBObject> toBaseOBObjects​(List<org.codehaus.jettison.json.JSONObject> jsonObjects)
        Converts a list with JSONObjects to a list of BaseOBObject instances. See the conversion logic description in the class header for more information.
        Parameters:
        jsonObjects - the list with JSONObjects
        Returns:
        the list of BaseOBObjects.
      • toBaseOBObject

        public BaseOBObject toBaseOBObject​(org.codehaus.jettison.json.JSONObject jsonObject)
                                    throws Exception
        Converts a single JSONObject to a BaseOBObject. See the conversion logic description in the class header for more information.
        Parameters:
        jsonObject - the jsonObject to convert
        Returns:
        the BaseOBObject (new or retrieved from the database)
        Throws:
        Exception
      • setData

        protected void setData​(org.codehaus.jettison.json.JSONObject jsonObject,
                               BaseOBObject obObject)
                        throws org.codehaus.jettison.json.JSONException
        Sets the data in the BaseOBObject by converting data from the json object and finding the correct properties to set.
        Parameters:
        jsonObject - the source of the data
        obObject - the target of the data
        Throws:
        org.codehaus.jettison.json.JSONException
      • handleMultiPathProperty

        protected void handleMultiPathProperty​(String previousPath,
                                               String remainingPath,
                                               BaseOBObject obObject,
                                               org.codehaus.jettison.json.JSONObject jsonObject,
                                               Object value)
                                        throws org.codehaus.jettison.json.JSONException
        Handles the complex case of keys in the JSONObject which consists of multiple steps. For example businessPartner.paymentTerm.name. To handle these keys the system has to walk the path and find the object at the end of the path to set the value. The system should take into account that not all objects along the path already exists, for example the paymentTerm in the businessPartner maybe null. In that case a new PaymentTerm needs to be set in the businessPartner. The system should also check if there is an id passed in for the paymentTerm: businessPartner.paymentTerm.id. If so then that one should be used to create/read the PaymentTerm. The previousPath and remainingPath parameters are used to keep track of the path walked. For example if the system is processing the part of the paymentTerm then the previousPath will be: 'businessPartner' and the remaining path will be: 'paymentTerm.name'.
        Parameters:
        previousPath - see part of the path which has been 'walked', is initially empty.
        remainingPath - the part which needs to be handled.
        obObject - the current BaseOBObject to set
        jsonObject - the jsonObject containing the values
        value - the value to set when the end of the path has been reached.
        Throws:
        org.codehaus.jettison.json.JSONException
      • getBaseOBObjectFromId

        protected BaseOBObject getBaseOBObjectFromId​(Entity entity,
                                                     Property property,
                                                     String referencedId)
        Tries to find an object first in the internal map which is maintained to first resolve id's internally within the complete json string. If not found there then the database is queried using the entity and referenceId. If not found there (or the referenceId == null) then create a new instance of the entity.
        Parameters:
        entity - the entity to retrieve/create
        property - the property referencing to the entity
        referencedId - the id of the entity
        Returns:
        an existing of new BaseOBObject
      • areDatesEqual

        protected boolean areDatesEqual​(Date d1,
                                        Date d2,
                                        boolean isDatetime,
                                        boolean isTime)
        The json conversion looses precision in milliseconds and seconds. This comparison method only compares the other parts of the date object. Depending if a date or a date time is set.
        Parameters:
        d1 - the first date to compare
        d2 - the second date to compare
        isDatetime - is it a datetime
        Returns:
        true if d1 and d2 have equal values for year, month and day and for date time also same values for hour, minutes and seconds.
      • areDatesEqual

        protected boolean areDatesEqual​(Date d1,
                                        Date d2,
                                        boolean isDatetime)
      • hasErrors

        public boolean hasErrors()