Skip to content

Commit

Permalink
Remove lazy loading for getSupportedObjects in Registration.
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Jun 3, 2021
1 parent 86cbd35 commit 7ba642a
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,29 @@ public boolean equals(Object obj) {
return true;
}

/**
* Parse a string containing a full LWM2M path containing rootpath (rt="oma.lwm2m").
* <p>
* E.g. : fullpath="/myrootpath/1/0 and rootpath="/myrootpat/" will return <code>new LwM2mPath(1,0)</code>
*
* @param fullpath the path to parse.
* @param lwm2mRootpath the expected rootpath. <code>null</code> is considered as "/"
* @return A valid {@link LwM2mPath} or null it does not start by lwm2mRootPath
*
* @exception NumberFormatException if path contains not Numeric value
* @exception LwM2mNodeException if path is invalid (e.g. too big number in path)
* @exception IllegalArgumentException if path length is invalid
*/
public static LwM2mPath parse(String fullpath, String lwm2mRootpath)
throws NumberFormatException, LwM2mNodeException, IllegalArgumentException {
if (lwm2mRootpath == null) {
return new LwM2mPath(fullpath);
}

if (!fullpath.startsWith(lwm2mRootpath))
return null;
String path = fullpath.substring(lwm2mRootpath.length());

return new LwM2mPath(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,12 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.leshan.core.Link;
import org.eclipse.leshan.core.LwM2m.Version;
import org.eclipse.leshan.core.attributes.Attribute;
import org.eclipse.leshan.core.model.ObjectModel;
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.core.request.Identity;
Expand Down Expand Up @@ -73,10 +71,6 @@ public class Registration {

private final Link[] objectLinks;

// Lazy Loaded map of supported object (object id => version)
// built from objectLinks
private final AtomicReference<Map<Integer, String>> supportedObjects;

private final Map<String, String> additionalRegistrationAttributes;

// The location where LWM2M objects are hosted on the device
Expand All @@ -85,6 +79,9 @@ public class Registration {
// All ContentFormat supported by the client
private final Set<ContentFormat> supportedContentFormats;

// All supported object (object id => version)
private final Map<Integer, String> supportedObjects;

private final Date lastUpdate;

protected Registration(Builder builder) {
Expand All @@ -102,7 +99,7 @@ protected Registration(Builder builder) {
objectLinks = builder.objectLinks;
rootPath = builder.rootPath;
supportedContentFormats = builder.supportedContentFormats;
supportedObjects = new AtomicReference<Map<Integer, String>>(builder.supportedObjects);
supportedObjects = builder.supportedObjects;

// other params
lifeTimeInSec = builder.lifeTimeInSec;
Expand Down Expand Up @@ -320,12 +317,7 @@ public String getSupportedVersion(Integer objectid) {
* @return a map from {@code objectId} {@literal =>} {@code supportedVersion} for each supported objects. supported.
*/
public Map<Integer, String> getSupportedObject() {
Map<Integer, String> objects = supportedObjects.get();
if (objects != null)
return objects;

supportedObjects.compareAndSet(null, Collections.unmodifiableMap(getSupportedObject(rootPath, objectLinks)));
return supportedObjects.get();
return supportedObjects;
}

@Override
Expand Down Expand Up @@ -356,6 +348,7 @@ public int hashCode() {
result = prime * result + ((rootPath == null) ? 0 : rootPath.hashCode());
result = prime * result + ((smsNumber == null) ? 0 : smsNumber.hashCode());
result = prime * result + ((supportedContentFormats == null) ? 0 : supportedContentFormats.hashCode());
result = prime * result + ((supportedObjects == null) ? 0 : supportedObjects.hashCode());
return result;
}

Expand Down Expand Up @@ -432,55 +425,14 @@ public boolean equals(Object obj) {
return false;
} else if (!supportedContentFormats.equals(other.supportedContentFormats))
return false;
if (supportedObjects == null) {
if (other.supportedObjects != null)
return false;
} else if (!supportedObjects.equals(other.supportedObjects))
return false;
return true;
}

/**
* Build a Map {@code objectId} {@literal =>} {@code supportedVersion} from root path and registration object links.
*
* @param rootPath the rootpath of LWM2M tree.
* @param objectLinks the registraiton object links payload.
* @return a Map {@code objectId} {@literal =>} {@code supportedVersion}.
*/
public static Map<Integer, String> getSupportedObject(String rootPath, Link[] objectLinks) {
Map<Integer, String> objects = new HashMap<>();
for (Link link : objectLinks) {
if (link != null) {
Pattern p = Pattern.compile("^\\Q" + rootPath + "\\E(\\d+)(?:/\\d+)*$");
Matcher m = p.matcher(link.getUrl());
if (m.matches()) {
try {
// extract object id and version
int objectId = Integer.parseInt(m.group(1));
String version = link.getAttributes().get(Attribute.OBJECT_VERSION);
// un-quote version (see https://github.com/eclipse/leshan/issues/732)
version = Link.unquote(version);
String currentVersion = objects.get(objectId);

// store it in map
if (currentVersion == null) {
// we never find version for this object add it
if (version != null) {
objects.put(objectId, version);
} else {
objects.put(objectId, ObjectModel.DEFAULT_VERSION);
}
} else {
// if version is already set, we override it only if new version is not DEFAULT_VERSION
if (version != null && !version.equals(ObjectModel.DEFAULT_VERSION)) {
objects.put(objectId, version);
}
}
} catch (NumberFormatException e) {
// This should not happened except maybe if the number in url is too long...
// In this case we just ignore it because this is not an object id.
}
}
}
}
return objects;
}

public static class Builder {
private final String registrationId;
private final String endpoint;
Expand Down Expand Up @@ -575,6 +527,11 @@ public Builder supportedContentFormats(ContentFormat... supportedContentFormats)
return this;
}

public Builder supportedObjects(Map<Integer, String> supportedObjects) {
this.supportedObjects = supportedObjects;
return this;
}

public Builder additionalRegistrationAttributes(Map<String, String> additionalRegistrationAttributes) {
this.additionalRegistrationAttributes = additionalRegistrationAttributes;
return this;
Expand All @@ -597,8 +554,8 @@ private void extractDataFromObjectLinks() {
}

// Extract data from link object
supportedObjects = new HashMap<>();
for (Link link : objectLinks) {
// TODO extract object supported
// TODO extract available instances

if (link != null) {
Expand All @@ -608,6 +565,14 @@ private void extractDataFromObjectLinks() {
if (ctValue != null) {
supportedContentFormats = extractContentFormat(ctValue);
}
} else {
LwM2mPath path = LwM2mPath.parse(link.getUrl(), rootPath);
if (path != null) {
// add supported objects
if (path.isObject() || path.isObjectInstance()) {
addSupportedObject(link, path);
}
}
}
}
}
Expand Down Expand Up @@ -643,6 +608,30 @@ private Set<ContentFormat> extractContentFormat(String ctValue) {
return supportedContentFormats;
}

private void addSupportedObject(Link link, LwM2mPath path) {
// extract object id and version
int objectId = path.getObjectId();
String version = link.getAttributes().get(Attribute.OBJECT_VERSION);
// un-quote version (see https://github.com/eclipse/leshan/issues/732)
version = Link.unquote(version);
String currentVersion = supportedObjects.get(objectId);

// store it in map
if (currentVersion == null) {
// we never find version for this object add it
if (version != null) {
supportedObjects.put(objectId, version);
} else {
supportedObjects.put(objectId, ObjectModel.DEFAULT_VERSION);
}
} else {
// if version is already set, we override it only if new version is not DEFAULT_VERSION
if (version != null && !version.equals(ObjectModel.DEFAULT_VERSION)) {
supportedObjects.put(objectId, version);
}
}
}

public Registration build() {
// Define Default value
rootPath = rootPath == null ? "/" : rootPath;
Expand All @@ -665,6 +654,11 @@ public Registration build() {
} else {
supportedContentFormats = Collections.unmodifiableSet(new HashSet<>(supportedContentFormats));
}
if (supportedObjects == null || supportedObjects.isEmpty()) {
supportedObjects = Collections.emptyMap();
} else {
supportedObjects = Collections.unmodifiableMap(new HashMap<>(supportedObjects));
}
if (additionalRegistrationAttributes == null || additionalRegistrationAttributes.isEmpty()) {
additionalRegistrationAttributes = Collections.emptyMap();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public Registration update(Registration registration) {
.bindingMode(bindingMode).queueMode(registration.getQueueMode()).objectLinks(linkObject)
.registrationDate(registration.getRegistrationDate()).lastUpdate(lastUpdate)
.additionalRegistrationAttributes(additionalAttributes).rootPath(registration.getRootPath())
.supportedContentFormats(registration.getSupportedContentFormats());
.supportedContentFormats(registration.getSupportedContentFormats())
.supportedObjects(registration.getSupportedObject());

return builder.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,10 @@ public void test_object_links_with_text_in_not_lwm2m_path() {
assertEquals("1.1", supportedObject.get(3));
}

@Test
@Test(expected = IllegalArgumentException.class)
public void test_object_links_with_text_in_lwm2m_path() {
Registration reg = given_a_registration_with_object_link_like(
given_a_registration_with_object_link_like(
"<text>,</1/text/0/in/path>,empty,</2/O/test/in/path>,</3/0>;ver=\"1.1\",</4/0/0/>");

// check root path
assertEquals("/", reg.getRootPath());

// Ensure supported objects are correct
Map<Integer, String> supportedObject = reg.getSupportedObject();
assertEquals(1, supportedObject.size());
assertEquals("1.1", supportedObject.get(3));
}

private Registration given_a_registration_with_object_link_like(String objectLinks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.leshan.core.Link;
Expand All @@ -30,6 +31,7 @@
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonObject.Member;
import com.eclipsesource.json.JsonValue;

/**
Expand Down Expand Up @@ -83,6 +85,13 @@ public static JsonObject jSerialize(Registration r) {
ct.add(contentFormat.getCode());
}
o.add("ct", ct);

// handle supported object
JsonObject so = Json.object();
for (Entry<Integer, String> supportedObject : r.getSupportedObject().entrySet()) {
so.add(supportedObject.getKey().toString(), supportedObject.getValue());
}
o.add("suppObjs", so);
return o;
}

Expand Down Expand Up @@ -156,6 +165,19 @@ public static Registration deserialize(JsonObject jObj) {
}
b.supportedContentFormats(supportedContentFormat);
}
// parse supported object
JsonValue so = jObj.get("suppObjs");
if (so == null) {
// Backward compatibility : if suppObjs doesn't exist we extract supported object from object link
b.extractDataFromObjectLink(true);
} else {
Map<Integer, String> supportedObject = new HashMap<>();
for (Member member : so.asObject()) {
supportedObject.put(Integer.parseInt(member.getName()), member.getValue().asString());
}
b.supportedObjects(supportedObject);
}

return b.build();
}

Expand Down

0 comments on commit 7ba642a

Please sign in to comment.