Search in sources :

Example 1 with JsonArrayEntry

use of org.eclipse.leshan.json.JsonArrayEntry in project leshan by eclipse.

the class LwM2mNodeJsonDecoder method parseJSON.

private static List<TimestampedLwM2mNode> parseJSON(JsonRootObject jsonObject, LwM2mPath path, LwM2mModel model, Class<? extends LwM2mNode> nodeClass) throws CodecException {
    LOG.trace("Parsing JSON content for path {}: {}", path, jsonObject);
    // Group JSON entry by time-stamp
    Map<Long, Collection<JsonArrayEntry>> jsonEntryByTimestamp = groupJsonEntryByTimestamp(jsonObject);
    // Extract baseName
    LwM2mPath baseName = extractAndValidateBaseName(jsonObject, path);
    if (baseName == null)
        // if no base name, use request path as base name
        baseName = path;
    // fill time-stamped nodes collection
    List<TimestampedLwM2mNode> timestampedNodes = new ArrayList<>();
    for (Entry<Long, Collection<JsonArrayEntry>> entryByTimestamp : jsonEntryByTimestamp.entrySet()) {
        // Group JSON entry by instance
        Map<Integer, Collection<JsonArrayEntry>> jsonEntryByInstanceId = groupJsonEntryByInstanceId(entryByTimestamp.getValue(), baseName);
        // Create lwm2m node
        LwM2mNode node;
        if (nodeClass == LwM2mObject.class) {
            Collection<LwM2mObjectInstance> instances = new ArrayList<>();
            for (Entry<Integer, Collection<JsonArrayEntry>> entryByInstanceId : jsonEntryByInstanceId.entrySet()) {
                Map<Integer, LwM2mResource> resourcesMap = extractLwM2mResources(entryByInstanceId.getValue(), baseName, model);
                instances.add(new LwM2mObjectInstance(entryByInstanceId.getKey(), resourcesMap.values()));
            }
            node = new LwM2mObject(baseName.getObjectId(), instances);
        } else if (nodeClass == LwM2mObjectInstance.class) {
            // validate we have resources for only 1 instance
            if (jsonEntryByInstanceId.size() != 1)
                throw new CodecException("One instance expected in the payload [path:%s]", path);
            // Extract resources
            Entry<Integer, Collection<JsonArrayEntry>> instanceEntry = jsonEntryByInstanceId.entrySet().iterator().next();
            Map<Integer, LwM2mResource> resourcesMap = extractLwM2mResources(instanceEntry.getValue(), baseName, model);
            // Create instance
            node = new LwM2mObjectInstance(instanceEntry.getKey(), resourcesMap.values());
        } else if (nodeClass == LwM2mResource.class) {
            // validate we have resources for only 1 instance
            if (jsonEntryByInstanceId.size() > 1)
                throw new CodecException("Only one instance expected in the payload [path:%s]", path);
            // Extract resources
            Map<Integer, LwM2mResource> resourcesMap = extractLwM2mResources(jsonEntryByInstanceId.values().iterator().next(), baseName, model);
            // validate there is only 1 resource
            if (resourcesMap.size() != 1)
                throw new CodecException("One resource should be present in the payload [path:%s]", path);
            node = resourcesMap.values().iterator().next();
        } else {
            throw new IllegalArgumentException("invalid node class: " + nodeClass);
        }
        // compute time-stamp
        Long timestamp = computeTimestamp(jsonObject.getBaseTime(), entryByTimestamp.getKey());
        // add time-stamped node
        timestampedNodes.add(new TimestampedLwM2mNode(timestamp, node));
    }
    return timestampedNodes;
}
Also used : ArrayList(java.util.ArrayList) LwM2mNode(org.eclipse.leshan.core.node.LwM2mNode) TimestampedLwM2mNode(org.eclipse.leshan.core.node.TimestampedLwM2mNode) LwM2mResource(org.eclipse.leshan.core.node.LwM2mResource) TimestampedLwM2mNode(org.eclipse.leshan.core.node.TimestampedLwM2mNode) LwM2mObjectInstance(org.eclipse.leshan.core.node.LwM2mObjectInstance) JsonArrayEntry(org.eclipse.leshan.json.JsonArrayEntry) Entry(java.util.Map.Entry) LwM2mPath(org.eclipse.leshan.core.node.LwM2mPath) Collection(java.util.Collection) LwM2mObject(org.eclipse.leshan.core.node.LwM2mObject) CodecException(org.eclipse.leshan.core.node.codec.CodecException) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) JsonArrayEntry(org.eclipse.leshan.json.JsonArrayEntry)

Example 2 with JsonArrayEntry

use of org.eclipse.leshan.json.JsonArrayEntry in project leshan by eclipse.

the class LwM2mNodeJsonDecoder method groupJsonEntryByTimestamp.

/**
 * Group all JsonArrayEntry by time-stamp
 *
 * @return a map (relativeTimestamp => collection of JsonArrayEntry)
 */
private static SortedMap<Long, Collection<JsonArrayEntry>> groupJsonEntryByTimestamp(JsonRootObject jsonObject) {
    SortedMap<Long, Collection<JsonArrayEntry>> result = new TreeMap<>(new Comparator<Long>() {

        @Override
        public int compare(Long o1, Long o2) {
            // - reverses natural order (most recent value in first)
            return Long.compare(o2 == null ? 0 : o2, o1 == null ? 0 : o1);
        }
    });
    for (JsonArrayEntry e : jsonObject.getResourceList()) {
        // Get time for this entry
        Long time = e.getTime();
        // Get jsonArray for this time-stamp
        Collection<JsonArrayEntry> jsonArray = result.get(time);
        if (jsonArray == null) {
            jsonArray = new ArrayList<>();
            result.put(time, jsonArray);
        }
        // Add it to the list
        jsonArray.add(e);
    }
    // Ensure there is at least one entry for null timestamp
    if (result.isEmpty()) {
        result.put((Long) null, new ArrayList<JsonArrayEntry>());
    }
    return result;
}
Also used : Collection(java.util.Collection) TreeMap(java.util.TreeMap) JsonArrayEntry(org.eclipse.leshan.json.JsonArrayEntry)

Example 3 with JsonArrayEntry

use of org.eclipse.leshan.json.JsonArrayEntry in project leshan by eclipse.

the class LwM2mNodeJsonDecoder method groupJsonEntryByInstanceId.

/**
 * Group all JsonArrayEntry by instanceId
 *
 * @param jsonEntries
 * @param baseName
 *
 * @return a map (instanceId => collection of JsonArrayEntry)
 */
private static Map<Integer, Collection<JsonArrayEntry>> groupJsonEntryByInstanceId(Collection<JsonArrayEntry> jsonEntries, LwM2mPath baseName) throws CodecException {
    Map<Integer, Collection<JsonArrayEntry>> result = new HashMap<>();
    for (JsonArrayEntry e : jsonEntries) {
        // Build resource path
        LwM2mPath nodePath = baseName.append(e.getName());
        // Validate path
        if (!nodePath.isResourceInstance() && !nodePath.isResource()) {
            throw new CodecException("Invalid path [%s] for resource, it should be a resource or a resource instance path", nodePath);
        }
        // Get jsonArray for this instance
        Collection<JsonArrayEntry> jsonArray = result.get(nodePath.getObjectInstanceId());
        if (jsonArray == null) {
            jsonArray = new ArrayList<>();
            result.put(nodePath.getObjectInstanceId(), jsonArray);
        }
        // Add it to the list
        jsonArray.add(e);
    }
    // Create an entry for an empty instance if possible
    if (result.isEmpty() && baseName.getObjectInstanceId() != null) {
        result.put(baseName.getObjectInstanceId(), new ArrayList<JsonArrayEntry>());
    }
    return result;
}
Also used : HashMap(java.util.HashMap) LwM2mPath(org.eclipse.leshan.core.node.LwM2mPath) Collection(java.util.Collection) CodecException(org.eclipse.leshan.core.node.codec.CodecException) JsonArrayEntry(org.eclipse.leshan.json.JsonArrayEntry)

Example 4 with JsonArrayEntry

use of org.eclipse.leshan.json.JsonArrayEntry in project leshan by eclipse.

the class LwM2mNodeJsonEncoder method encodeTimestampedData.

public static byte[] encodeTimestampedData(List<TimestampedLwM2mNode> timestampedNodes, LwM2mPath path, LwM2mModel model, LwM2mValueConverter converter) {
    Validate.notNull(timestampedNodes);
    Validate.notNull(path);
    Validate.notNull(model);
    InternalEncoder internalEncoder = new InternalEncoder();
    ArrayList<JsonArrayEntry> entries = new ArrayList<>();
    for (TimestampedLwM2mNode timestampedLwM2mNode : timestampedNodes) {
        internalEncoder.objectId = path.getObjectId();
        internalEncoder.model = model;
        internalEncoder.requestPath = path;
        internalEncoder.converter = converter;
        internalEncoder.resourceList = null;
        internalEncoder.timestamp = timestampedLwM2mNode.getTimestamp();
        timestampedLwM2mNode.getNode().accept(internalEncoder);
        entries.addAll(internalEncoder.resourceList);
    }
    JsonRootObject jsonObject = new JsonRootObject();
    jsonObject.setResourceList(entries);
    jsonObject.setBaseName(path.toString());
    return LwM2mJson.toJsonLwM2m(jsonObject).getBytes();
}
Also used : TimestampedLwM2mNode(org.eclipse.leshan.core.node.TimestampedLwM2mNode) ArrayList(java.util.ArrayList) JsonRootObject(org.eclipse.leshan.json.JsonRootObject) JsonArrayEntry(org.eclipse.leshan.json.JsonArrayEntry)

Example 5 with JsonArrayEntry

use of org.eclipse.leshan.json.JsonArrayEntry in project leshan by eclipse.

the class LwM2mNodeJsonDecoder method extractLwM2mResources.

private static Map<Integer, LwM2mResource> extractLwM2mResources(Collection<JsonArrayEntry> jsonArrayEntries, LwM2mPath baseName, LwM2mModel model) throws CodecException {
    if (jsonArrayEntries == null)
        return Collections.emptyMap();
    // Extract LWM2M resources from JSON resource list
    Map<Integer, LwM2mResource> lwM2mResourceMap = new HashMap<>();
    Map<LwM2mPath, Map<Integer, JsonArrayEntry>> multiResourceMap = new HashMap<>();
    for (JsonArrayEntry resourceElt : jsonArrayEntries) {
        // Build resource path
        LwM2mPath nodePath = baseName.append(resourceElt.getName());
        // handle LWM2M resources
        if (nodePath.isResourceInstance()) {
            // Multi-instance resource
            // Store multi-instance resource values in a map
            // we will deal with it later
            LwM2mPath resourcePath = new LwM2mPath(nodePath.getObjectId(), nodePath.getObjectInstanceId(), nodePath.getResourceId());
            Map<Integer, JsonArrayEntry> multiResource = multiResourceMap.get(resourcePath);
            if (multiResource == null) {
                multiResource = new HashMap<>();
                multiResourceMap.put(resourcePath, multiResource);
            }
            multiResource.put(nodePath.getResourceInstanceId(), resourceElt);
        } else if (nodePath.isResource()) {
            // Single resource
            Type expectedType = getResourceType(nodePath, model, resourceElt);
            LwM2mResource res = LwM2mSingleResource.newResource(nodePath.getResourceId(), parseJsonValue(resourceElt.getResourceValue(), expectedType, nodePath), expectedType);
            lwM2mResourceMap.put(nodePath.getResourceId(), res);
        } else {
            throw new CodecException("Invalid path [%s] for resource, it should be a resource or a resource instance path", nodePath);
        }
    }
    // Handle multi-instance resource.
    for (Map.Entry<LwM2mPath, Map<Integer, JsonArrayEntry>> entry : multiResourceMap.entrySet()) {
        LwM2mPath resourcePath = entry.getKey();
        Map<Integer, JsonArrayEntry> jsonEntries = entry.getValue();
        if (jsonEntries != null && !jsonEntries.isEmpty()) {
            Type expectedType = getResourceType(resourcePath, model, jsonEntries.values().iterator().next());
            Map<Integer, Object> values = new HashMap<>();
            for (Entry<Integer, JsonArrayEntry> e : jsonEntries.entrySet()) {
                Integer resourceInstanceId = e.getKey();
                values.put(resourceInstanceId, parseJsonValue(e.getValue().getResourceValue(), expectedType, resourcePath));
            }
            LwM2mResource resource = LwM2mMultipleResource.newResource(resourcePath.getResourceId(), values, expectedType);
            lwM2mResourceMap.put(resourcePath.getResourceId(), resource);
        }
    }
    // If we found nothing, we try to create an empty multi-instance resource
    if (lwM2mResourceMap.isEmpty() && baseName.isResource()) {
        ResourceModel resourceModel = model.getResourceModel(baseName.getObjectId(), baseName.getResourceId());
        // We create it only if this respect the model
        if (resourceModel == null || resourceModel.multiple) {
            Type resourceType = getResourceType(baseName, model, null);
            lwM2mResourceMap.put(baseName.getResourceId(), LwM2mMultipleResource.newResource(baseName.getResourceId(), new HashMap<Integer, Object>(), resourceType));
        }
    }
    return lwM2mResourceMap;
}
Also used : HashMap(java.util.HashMap) LwM2mResource(org.eclipse.leshan.core.node.LwM2mResource) Type(org.eclipse.leshan.core.model.ResourceModel.Type) LwM2mPath(org.eclipse.leshan.core.node.LwM2mPath) ResourceModel(org.eclipse.leshan.core.model.ResourceModel) CodecException(org.eclipse.leshan.core.node.codec.CodecException) JsonRootObject(org.eclipse.leshan.json.JsonRootObject) LwM2mObject(org.eclipse.leshan.core.node.LwM2mObject) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) JsonArrayEntry(org.eclipse.leshan.json.JsonArrayEntry)

Aggregations

JsonArrayEntry (org.eclipse.leshan.json.JsonArrayEntry)5 Collection (java.util.Collection)3 HashMap (java.util.HashMap)3 TreeMap (java.util.TreeMap)3 LwM2mPath (org.eclipse.leshan.core.node.LwM2mPath)3 CodecException (org.eclipse.leshan.core.node.codec.CodecException)3 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2 SortedMap (java.util.SortedMap)2 LwM2mObject (org.eclipse.leshan.core.node.LwM2mObject)2 LwM2mResource (org.eclipse.leshan.core.node.LwM2mResource)2 TimestampedLwM2mNode (org.eclipse.leshan.core.node.TimestampedLwM2mNode)2 JsonRootObject (org.eclipse.leshan.json.JsonRootObject)2 Entry (java.util.Map.Entry)1 ResourceModel (org.eclipse.leshan.core.model.ResourceModel)1 Type (org.eclipse.leshan.core.model.ResourceModel.Type)1 LwM2mNode (org.eclipse.leshan.core.node.LwM2mNode)1 LwM2mObjectInstance (org.eclipse.leshan.core.node.LwM2mObjectInstance)1