Axeda: Helper Functions for Extended Objects

    This is a collection of methods for working with ExtendedObjects based on the functions used in Fleetster.


    import com.axeda.drm.sdk.device.Device
    import com.axeda.platform.sdk.v1.services.ServiceFactory
    import com.axeda.platform.sdk.v1.services.extobject.ExtendedObjectSearchCriteria
    import com.axeda.platform.sdk.v1.services.extobject.PropertySearchCriteria
    import com.axeda.platform.sdk.v1.services.extobject.expression.PropertyExpressionFactory
    import com.axeda.drm.sdk.data.CurrentDataFinder
    import com.axeda.platform.sdk.v1.services.extobject.ExtendedObject
    import com.axeda.platform.sdk.v1.services.extobject.Property
    import java.text.DecimalFormat
    import com.axeda.drm.sdk.Context
    import com.axeda.drm.sdk.device.DeviceDataFinder
    import com.axeda.drm.sdk.user.User
    import com.axeda.platform.sdk.v1.services.extobject.ExtendedObjectService
    import com.axeda.platform.sdk.v1.services.extobject.PropertyType
    import com.axeda.platform.sdk.v1.services.extobject.PropertyDataType
    import com.axeda.platform.sdk.v1.services.extobject.ExtendedObjectType
    import com.axeda.common.sdk.id.Identifier
    import groovy.time.*
    
    /* ************************************* */
    /* HelperFunctionsExtendedObjects.groovy
    * Extended Object retrieval/manipulation functions.
    *
    * A collection of methods for working with ExtendedObjects.
    *
    * author: sara streeter <sstreeter@axeda.com>
    ************************************* */
    
        def eoSvc = new ServiceFactory().getExtendedObjectService()
    
        def fetchFirstExtendedObject(DataItem dataItem, Map searchcriteria) {
            def criteria = new ExtendedObjectSearchCriteria()
            criteria.extendedObjectClassName = 'com.axeda.drm.sdk.device.DataItem'
            criteria.internalObjectId = dataItem.id.value
            criteria.extendedClientKey = "ExtendedDataItem!${dataItem.name}"
            def eo
          if (searchcriteria != null){
                criteria.propertySearchCriteria = advancedPropertySearch(searchcriteria)
            }
           def queryResult = eoSvc.findExtendedObjects(criteria,  -1, -1, null)
            if (queryResult.size() > 0 ){
            eo = queryResult.first()
            }
    
           return eo
        }
    
       def addOrFetchExtendedDataItem(DataItem dataItem, Map searchcriteria) {
            def criteria = new ExtendedObjectSearchCriteria()
            criteria.extendedObjectClassName = 'com.axeda.drm.sdk.device.DataItem'
            criteria.internalObjectId = dataItem.id.value
            criteria.extendedClientKey = "ExtendedDataItem!${dataItem.name}"
            def eo
          if (searchcriteria != null){
                criteria.propertySearchCriteria = advancedPropertySearch(searchcriteria)
            }
           def queryResult = eoSvc.findExtendedObjects(criteria,  -1, -1, null)
    
           if (queryResult.size() == 0 || queryResult == null){
                  eo = new ExtendedObject()
                  eo.internalObjectId = dataItem.id.value
                  eo.extendedObjectType = eoSvc.findExtendedObjectTypeByClassname('com.axeda.drm.sdk.device.DataItem')
                  eo.externalClientKey = "ExtendedDataItem!${dataItem.name}"
                  eo = eoSvc.createExtendedObject(eo)
                searchcriteria += [eotype: "ExtendedObject"]
                createProperties(eoSvc, eo, searchcriteria)
             }
            else eo = queryResult.first()
    
           return eo
        }
    
       def fetchExtendedDataItem(DataItem dataItem) {
            def criteria = new ExtendedObjectSearchCriteria()
            criteria.extendedObjectClassName = "com.axeda.drm.sdk.device.DataItem"
            criteria.extendedClientKey = "ExtendedDataItem!${dataItem.name}"
            criteria.internalObjectId = dataItem.id.value
           def queryResult = eoSvc.findExtendedObjects(criteria,  -1, -1, null)
            return queryResult
        }
    
       def fetchExtendedObjectsAdvancedCriteria(DataItem dataItem, Map searchcriteria, String classname, String uniqueKey) {
            def criteria = new ExtendedObjectSearchCriteria()
            criteria.extendedObjectClassName = "com.axeda.drm.sdk.device.DataItem"
            criteria.extendedClientKey = "ExtendedDataItem!${dataItem.name}"
            criteria.internalObjectId = dataItem.id.value
           if (searchcriteria != null){
                criteria.propertySearchCriteria = advancedPropertySearch(searchcriteria)
            }
           def queryResult = eoSvc.findExtendedObjects(criteria,  -1, -1, null)
            return queryResult
        }
    
       def fetchExtendedObject(User user, Map searchcriteria) {
            def criteria = new ExtendedObjectSearchCriteria()
            criteria.extendedObjectClassName = "com.axeda.drm.sdk.user.User"
            criteria.extendedClientKey = "ExtendedObject!${user.username}"
            criteria.internalObjectId = user.id.value
            criteria.propertySearchCriteria = exactdatePropertySearch(searchcriteria)
            def queryResult = eoSvc.findExtendedObjects(criteria, -1, -1, null)
            return queryResult
        }
    
       def addExtendedObject(String eoTypeName, Long referenceId, String referenceName, Map objectProperties) {
          def eo = new ExtendedObject()
          eo.internalObjectId = referenceId
          eo.extendedObjectType = eoSvc.findExtendedObjectTypeByClassname(eoTypeName)
          eo.externalClientKey = referenceName
          eo = eoSvc.createExtendedObject(eo)
    
          eo = createProperties(eoSvc, eo, objectProperties)
    
           return eo
        }
    
       def updateExtendedObject(ExtendedObject ExtendedObject, ExtendedObject ExtendedObject) {
                    def ExtendedObjectprop = getProperties(ExtendedObject)
                    def ExtendedObjectprop = getProperties(ExtendedObject)
    
                    def newproperties = [:]
                    if (ExtendedObjectprop.timestamp != null){
    
                    def ExtendedObjecttype = ExtendedObjectprop.lasttype
                    def ExtendedObjecttime = ExtendedObjectprop.lasttime
                    if (ExtendedObjecttype == null){
                        newproperties["lasttype"] = ExtendedObjectprop.type
                        newproperties["lasttime"] = ExtendedObjectprop.timestamp
                    }
                    else {
                        def oldtime = Long.valueOf(ExtendedObjecttime)
                        def total = (Long.valueOf(ExtendedObjectprop.timestamp) - oldtime)/1000
                        // illustrating getPropertyByName /
                        def lasttype = ExtendedObject.getPropertyByName("lasttype")
    
                        lasttype.setValue(ExtendedObjectprop.type)
                        def lasttime = ExtendedObject.getPropertyByName("lasttime")
                        lasttime.setValue(ExtendedObjectprop.timestamp)
                        updateProperty(lasttype)
                        updateProperty(lasttime)
                        if (ExtendedObjectprop.containsKey(ExtendedObjecttype + "_total")==false)
                            {
    
                                newproperties[ExtendedObjecttype + "_total"] = total
                            }
                        else {
                            def totalprop = ExtendedObject.getPropertyByName(ExtendedObjecttype + "_total")
                            def lasttotal = Double.valueOf(totalprop.value)
                            totalprop.setValue(String.valueOf(Double.valueOf(total) + lasttotal))
                            updateProperty(totalprop)
                        }
                    }
    
                    if (newproperties.size() > 0){
                        ExtendedObject = createProperties(eoSvc, ExtendedObject, newproperties)
                    }
            }
    
            return ExtendedObject
       }
    
        def getProperties(ExtendedObject object){
            def result = object.properties.inject([:]) { target, property ->
                  target += [(property.propertyType.name): castPropertyValueToDefinedType(property)]
                }
            return result
        }
    
        def formatProperties(Map properties){
            def result = properties.collect { property, value ->
                   [type: property, time: value]
                }
            return result
        }
    
    def updateProperty(Property property){
            eoSvc.updateProperty(property)
            return property
    }
    
        //default string version
        def createProperties (ExtendedObjectService eoSvc, ExtendedObject object, Map properties) {
            return createProperties(eoSvc, object, properties, PropertyDataType.String)
        }
      
        //WARNING: PDT may not work if it's a Date; it hasn't been tested.
        def createProperties (ExtendedObjectService eoSvc, ExtendedObject object, Map properties, PropertyDataType PDT) {
           // http://groovy.codehaus.org/Operators#Operators-ElvisOperator
            PDT = PDT?:PropertyDataType.String
    
            properties.each { k , v ->
                def property = new com.axeda.platform.sdk.v1.services.extobject.Property()
                def propertytype = object.extendedObjectType.getPropertyTypeByName(k.toString())
                if (propertytype == null){
                    def newPropertyType = new PropertyType()
                    newPropertyType.name = k
                    newPropertyType.dataType = PDT
                    newPropertyType.extendedObjectType = object.extendedObjectType
                    eoSvc.createPropertyType(newPropertyType)
                    property.propertyType = newPropertyType
                } else { property.propertyType = propertytype }
    
                property.value = (PDT == PropertyDataType.Date && v instanceof Date?v.format("yyyy-MM-ddTHH:mm:ssZ"):v.toString())
                eoSvc.createPropertyOnExtendedObject(object, property)
            }
            object = findExtendedObjectById(object.id)
            return object
        }
    
        def findExtendedObjectById(Long id){
            def criteria = new ExtendedObjectSearchCriteria()
            criteria.id = id
            def queryResult = eoSvc.findExtendedObjects(criteria,  -1, -1, null)
            return queryResult.first()
    }
    
    
        def findObjectByNextPropertyValue (ExtendedObject object, Map criteria, PropertySearchCriteria psCriteria){
    
           Property prop = object.getPropertyByName(criteria.incrementName)
           def incrementedProp = prop.value.toInteger() + criteria.incrementValue.toInteger()
               psCriteria.setPropertyExpression(
               PropertyExpressionFactory.and(
                        psCriteria.propertyExpression,
                        PropertyExpressionFactory.eq(criteria.incrementName, incrementedProp.toString())
                       )
                )
           def eoCriteria = new ExtendedObjectSearchCriteria()
            eoCriteria.extendedObjectClassName = "com.axeda.drm.sdk.user.User"
            eoCriteria.internalObjectId = object.internalObjectId
            eoCriteria.propertySearchCriteria = psCriteria
           def queryResult = eoSvc.findExtendedObjects(eoCriteria,  -1, -1, null)
           return queryResult.first()
    
        }
    
        def advancedPropertySearch (Map searchcriteria){
              def propCriteria = new PropertySearchCriteria()
           propCriteria.setPropertyExpression(
               PropertyExpressionFactory.and(
                   PropertyExpressionFactory.eq("year", searchcriteria.year),
                        PropertyExpressionFactory.and(
                            PropertyExpressionFactory.eq("month", searchcriteria.month),
                                        PropertyExpressionFactory.eq("date", searchcriteria.date)
                                )
                       )
                )
            return propCriteria
    
        }
    
      static def extendedObjectToMap(ExtendedObject object) {
        Map result = [:]
    
        result.extendedObjectType = object?.extendedObjectType?.className
        result.extendedObjectTypeId = object?.extendedObjectTypeId
        result.id = object?.id
        result.externalClientKey = object?.externalClientKey
        result.internalObjectId = object?.internalObjectId
    
        // build up the properties of the ExtendedObject.
        result.properties = object?.properties.inject([:]) { target, property ->
          target += [(property?.propertyType?.name): castPropertyValueToDefinedType(property)]
        }
    
        return result
      }
    
          static def extendedObjectTypeToMap(ExtendedObjectType objectType) {
            Map result = [:]
    
            result.className = objectType.className
            result.id = objectType.id
            result.displayName  = objectType.displayName
            result.userDefined = objectType.userDefined
            result.description = objectType.description
    
            result.properties = objectType.propertyTypes.inject([]) { List list, PropertyType propertyType ->
              list << [
                      name: propertyType.name,
                      id: propertyType.id,
                      description: propertyType.description,
                      dataType: propertyType.dataType.toString(),
                      extendedObjectType: propertyType.extendedObjectType.className
              ]
            }
    
            return result
          }
    
          private static def castPropertyValueToDefinedType(Property property) {
            switch(property.propertyType.dataType) {
              case PropertyDataType.Boolean:
                return property.value as Boolean
              case PropertyDataType.Date:
                Calendar calendar = javax.xml.bind.DatatypeConverter.parseDateTime(property.value)
                return calendar.getTime()
              case PropertyDataType.Double:
                return property.value as Double
              case PropertyDataType.Integer:
                return property.value as Long
              case PropertyDataType.String:
              default:
                return property.value
            }
          }
    
    
          static def removeExtendedObject(Long itemId) {
            def eoSvc = new ServiceFactory().getExtendedObjectService()
            eoSvc.deleteExtendedObject(itemId)
          }
    
          def removeUserExtendedObjects(User user) {
            def queryresult = fetchUserExtendedObjects(user)
            queryresult.each{
                    eoSvc.deleteExtendedObject(it.id)
            }
          }
        
      ExtendedObjectType findExtendedObjectType(String typeName) {
        ExtendedObjectType userObjType = eoSvc.findExtendedObjectTypeByClassname(typeName)
        return userObjType
      }
    
      ExtendedObjectType findOrCreateExtendedObjectType(String typeName) {
        ExtendedObjectType type = findExtendedObjectType(typeName)
        if (type == null) {
          type = new ExtendedObjectType()
          type.className = typeName
          type.displayName = typeName
          type.description = "Autocreated type for $typeName"
    
          type = eoSvc.createExtendedObjectType(type)
        }
        return type
      }