org.eclipse.leshan.server.redis.serialization.RegistrationSerDes Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2016 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
* Orange - keep one JSON dependency
*******************************************************************************/
package org.eclipse.leshan.server.redis.serialization;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.leshan.core.LwM2m.LwM2mVersion;
import org.eclipse.leshan.core.LwM2m.Version;
import org.eclipse.leshan.core.endpoint.DefaultEndPointUriHandler;
import org.eclipse.leshan.core.endpoint.EndPointUriHandler;
import org.eclipse.leshan.core.endpoint.EndpointUri;
import org.eclipse.leshan.core.link.Link;
import org.eclipse.leshan.core.link.attributes.Attribute;
import org.eclipse.leshan.core.link.attributes.AttributeModel;
import org.eclipse.leshan.core.link.attributes.AttributeParser;
import org.eclipse.leshan.core.link.attributes.Attributes;
import org.eclipse.leshan.core.link.attributes.DefaultAttributeParser;
import org.eclipse.leshan.core.link.attributes.InvalidAttributeException;
import org.eclipse.leshan.core.link.lwm2m.MixedLwM2mLink;
import org.eclipse.leshan.core.link.lwm2m.attributes.LwM2mAttributes;
import org.eclipse.leshan.core.link.lwm2m.attributes.MixedLwM2mAttributeSet;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.request.BindingMode;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.server.registration.Registration;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Functions for serialize and deserialize a Client in JSON.
*/
public class RegistrationSerDes {
private final AttributeParser attributeParser;
private final LwM2mPeerSerDes peerSerDes;
private final EndPointUriHandler uriHandler;
public RegistrationSerDes(LwM2mPeerSerDes peerSerDes) {
// Define all supported Attributes
Collection> suppportedAttributes = new ArrayList>();
suppportedAttributes.addAll(Attributes.ALL);
suppportedAttributes.addAll(LwM2mAttributes.ALL);
// Create default link Parser
this.attributeParser = new DefaultAttributeParser(suppportedAttributes);
this.peerSerDes = peerSerDes;
this.uriHandler = new DefaultEndPointUriHandler();
}
public RegistrationSerDes() {
this(new DefaultAttributeParser(), new LwM2mPeerSerDes());
}
public RegistrationSerDes(AttributeParser attributeParser, LwM2mPeerSerDes peerSerDes) {
this(attributeParser, peerSerDes, new DefaultEndPointUriHandler());
}
public RegistrationSerDes(AttributeParser attributeParser, LwM2mPeerSerDes peerSerDes,
EndPointUriHandler uriHandler) {
this.attributeParser = attributeParser;
this.peerSerDes = peerSerDes;
this.uriHandler = uriHandler;
}
public JsonNode jSerialize(Registration r) {
ObjectNode o = JsonNodeFactory.instance.objectNode();
o.put("regDate", r.getRegistrationDate().getTime());
// TODO handle backward compatibility ?
// o.set("identity", IdentitySerDes.serialize(r.getIdentity()));
o.set("transportdata", peerSerDes.serialize(r.getClientTransportData()));
o.put("lt", r.getLifeTimeInSec());
if (r.getSmsNumber() != null) {
o.put("sms", r.getSmsNumber());
}
o.put("ver", r.getLwM2mVersion().toString());
o.put("bnd", BindingMode.toString(r.getBindingMode()));
if (r.getQueueMode() != null)
o.put("qm", r.getQueueMode());
o.put("ep", r.getEndpoint());
o.put("regId", r.getId());
o.put("epUri", r.getLastEndpointUsed().toString());
ArrayNode links = JsonNodeFactory.instance.arrayNode();
for (Link l : r.getObjectLinks()) {
ObjectNode ol = JsonNodeFactory.instance.objectNode();
ol.put("url", l.getUriReference());
ObjectNode at = JsonNodeFactory.instance.objectNode();
for (Attribute a : l.getAttributes()) {
if (a.hasValue()) {
at.put(a.getName(), a.getCoreLinkValue());
} else {
at.set(a.getName(), null);
}
}
ol.set("at", at);
links.add(ol);
}
o.set("objLink", links);
ObjectNode addAttr = JsonNodeFactory.instance.objectNode();
for (Map.Entry e : r.getAdditionalRegistrationAttributes().entrySet()) {
addAttr.put(e.getKey(), e.getValue());
}
o.set("addAttr", addAttr);
o.put("root", r.getRootPath());
o.put("lastUp", r.getLastUpdate().getTime());
// add supported content format
Set supportedContentFormat = r.getSupportedContentFormats();
ArrayNode ct = JsonNodeFactory.instance.arrayNode();
for (ContentFormat contentFormat : supportedContentFormat) {
ct.add(contentFormat.getCode());
}
o.set("ct", ct);
// handle supported object
ObjectNode so = JsonNodeFactory.instance.objectNode();
for (Entry supportedObject : r.getSupportedObject().entrySet()) {
so.put(supportedObject.getKey().toString(), supportedObject.getValue().toString());
}
o.set("suppObjs", so);
// handle available instances
ArrayNode ai = JsonNodeFactory.instance.arrayNode();
for (LwM2mPath instance : r.getAvailableInstances()) {
ai.add(instance.toString());
}
o.set("objInstances", ai);
// handle application data
ObjectNode ad = JsonNodeFactory.instance.objectNode();
for (Entry appData : r.getApplicationData().entrySet()) {
ad.put(appData.getKey(), appData.getValue());
}
o.set("appdata", ad);
return o;
}
public String sSerialize(Registration r) {
return jSerialize(r).toString();
}
public byte[] bSerialize(Registration r) {
return jSerialize(r).toString().getBytes();
}
public Registration deserialize(JsonNode jObj) {
EndpointUri lastEndpointUsed;
try {
lastEndpointUsed = uriHandler.createUri(jObj.get("epUri").asText());
} catch (IllegalStateException e1) {
throw new IllegalStateException(
String.format("Unable to deserialize last endpoint used URI %s of registration %s/%s",
jObj.get("epUri").asText(), jObj.get("regId").asText(), jObj.get("ep").asText()));
}
// TODO handle backward compatibility ?
// Registration.Builder b = new Registration.Builder(jObj.get("regId").asText(), jObj.get("ep").asText(),
// IdentitySerDes.deserialize(jObj.get("identity")), lastEndpointUsed);
Registration.Builder b = new Registration.Builder(jObj.get("regId").asText(), jObj.get("ep").asText(),
peerSerDes.deserialize(jObj.get("transportdata")), lastEndpointUsed);
b.bindingMode(BindingMode.parse(jObj.get("bnd").asText()));
if (jObj.get("qm") != null)
b.queueMode(jObj.get("qm").asBoolean());
b.lastUpdate(new Date(jObj.get("lastUp").asLong(0)));
b.lifeTimeInSec(jObj.get("lt").asLong(0));
String versionAsString = jObj.get("ver").asText();
LwM2mVersion lwm2mVersion = versionAsString == null ? LwM2mVersion.getDefault()
: LwM2mVersion.get(versionAsString);
b.lwM2mVersion(lwm2mVersion);
b.registrationDate(new Date(jObj.get("regDate").asLong(0)));
if (jObj.get("sms") != null) {
b.smsNumber(jObj.get("sms").asText(""));
}
String rootPath = jObj.get("root").asText("/");
b.rootPath(rootPath);
ArrayNode links = (ArrayNode) jObj.get("objLink");
Link[] linkObjs = new Link[links.size()];
for (int i = 0; i < links.size(); i++) {
ObjectNode ol = (ObjectNode) links.get(i);
List atts = new ArrayList<>();
JsonNode att = ol.get("at");
for (Iterator it = att.fieldNames(); it.hasNext();) {
String k = it.next();
JsonNode jsonValue = att.get(k);
String attValue;
if (jsonValue.isNull()) {
attValue = null;
} else {
if (jsonValue.isNumber()) {
// This else block is just needed for retro-compatibility
attValue = Integer.toString(jsonValue.asInt());
} else {
attValue = jsonValue.asText();
}
}
try {
atts.add(attributeParser.parseCoreLinkValue(k, attValue));
} catch (InvalidAttributeException e) {
throw new IllegalStateException(
String.format("Unable to deserialize attribute value from links of registraiton %s/%s",
jObj.get("regId").asText(), jObj.get("ep").asText()));
}
}
// handle lwm2m path
String path = ol.get("url").asText();
Link o;
if (path.startsWith(rootPath)) {
LwM2mPath lwm2mPath = LwM2mPath.parse(path, rootPath);
o = new MixedLwM2mLink(rootPath, lwm2mPath, new MixedLwM2mAttributeSet(atts));
} else {
o = new Link(path, atts);
}
linkObjs[i] = o;
}
b.objectLinks(linkObjs);
// parse additional attributes
Map addAttr = new HashMap<>();
ObjectNode o = (ObjectNode) jObj.get("addAttr");
for (Iterator it = o.fieldNames(); it.hasNext();) {
String k = it.next();
addAttr.put(k, o.get(k).asText(""));
}
b.additionalRegistrationAttributes(addAttr);
// parse supported content format
JsonNode ct = jObj.get("ct");
if (ct == null) {
throw new IllegalStateException(
String.format("Missing supported content format 'ct' field for registraiton %s/%s",
jObj.get("regId").asText(), jObj.get("ep").asText()));
} else {
Set supportedContentFormat = new HashSet<>();
for (JsonNode ctCode : ct) {
supportedContentFormat.add(ContentFormat.fromCode(ctCode.asInt()));
}
b.supportedContentFormats(supportedContentFormat);
}
// parse supported object
JsonNode so = jObj.get("suppObjs");
if (so == null) {
throw new IllegalStateException(String.format("Missing supported object 'so' field for registraiton %s/%s",
jObj.get("regId").asText(), jObj.get("ep").asText()));
} else {
Map supportedObject = new HashMap<>();
for (Iterator it = so.fieldNames(); it.hasNext();) {
String key = it.next();
supportedObject.put(Integer.parseInt(key), new Version(so.get(key).asText()));
}
b.supportedObjects(supportedObject);
}
// parse available instances
JsonNode ai = jObj.get("objInstances");
if (ai == null) {
throw new IllegalStateException(
String.format("Missing available instances 'ai' field for registraiton %s/%s",
jObj.get("regId").asText(), jObj.get("ep").asText()));
} else {
Set availableInstances = new HashSet<>();
for (JsonNode aiPath : ai) {
availableInstances.add(new LwM2mPath(aiPath.asText()));
}
b.availableInstances(availableInstances);
}
// parse app data
Map appData = new HashMap<>();
ObjectNode oap = (ObjectNode) jObj.get("appdata");
for (Iterator it = oap.fieldNames(); it.hasNext();) {
String key = it.next();
JsonNode jv = oap.get(key);
if (jv.isNull()) {
appData.put(key, null);
} else {
appData.put(key, jv.asText());
}
}
b.applicationData(appData);
return b.build();
}
public Registration deserialize(byte[] data) {
String json = new String(data);
try {
return deserialize(new ObjectMapper().readTree(json));
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(String.format("Unable to deserialize Registration %s", json), e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy