Skip to content

Commit

Permalink
Add LwM2mChildNode class to prepare addition of LwM2mRootNode
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Nov 10, 2023
1 parent fb44989 commit 4fa2c80
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 76 deletions.
@@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2023 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
*******************************************************************************/
package org.eclipse.leshan.core.node;

/**
* A child node in the LWM2M resource tree: Objects, Object instances, Resources or Resource instances.
*/
public interface LwM2mChildNode extends LwM2mNode {

/**
* @return the node identifier
*/
int getId();

/**
* Convert node to pretty string
*
* @param path of this node;
*/
String toPrettyString(LwM2mPath path);

/**
* Append pretty node to given {@link StringBuilder}
*
* @param b string builder to which node should be appended
* @param path of this node;
*/
StringBuilder appendPrettyNode(StringBuilder b, LwM2mPath path);
}
Expand Up @@ -16,32 +16,12 @@
package org.eclipse.leshan.core.node;

/**
* A node in the LWM2M resource tree: Objects, Object instances and Resources.
* A node in the LWM2M resource tree: Root, Objects, Object instances, Resources or Resource instances.
*/
public interface LwM2mNode {

/**
* @return the node identifier
*/
int getId();

/**
* Accept a visitor for this node.
*/
void accept(LwM2mNodeVisitor visitor);

/**
* Convert node to pretty string
*
* @param path of this node;
*/
String toPrettyString(LwM2mPath path);

/**
* Append pretty node to given {@link StringBuilder}
*
* @param b string builder to which node should be appended
* @param path of this node;
*/
StringBuilder appendPrettyNode(StringBuilder b, LwM2mPath path);
}
Expand Up @@ -268,38 +268,44 @@ public static void validateIncompletePath(LwM2mPath path) throws InvalidLwM2mPat
}

public static String getInvalidPathForNodeCause(LwM2mNode node, LwM2mPath path) {
if (node instanceof LwM2mObject) {
// Handle Root Node
if (!(node instanceof LwM2mChildNode))
return String.format("Invalid Path %s : path does not target a root node for %s", path, node);

// Handle child Node
LwM2mChildNode childNode = (LwM2mChildNode) node;
if (childNode instanceof LwM2mObject) {
if (!path.isObject()) {
return String.format("Invalid Path %s : path does not target a LWM2M object for %s", path, node);
} else if (node.getId() != path.getObjectId()) {
return String.format("Invalid Path %s : path does not target a LWM2M object for %s", path, childNode);
} else if (childNode.getId() != path.getObjectId()) {
return String.format("Invalid Path %s : path object id (%d) does not match LWM2M object id %d for %s",
path, path.getObjectId(), node.getId(), node);
path, path.getObjectId(), childNode.getId(), childNode);
}
} else if (node instanceof LwM2mObjectInstance) {
} else if (childNode instanceof LwM2mObjectInstance) {
if (!path.isObjectInstance()) {
return String.format("Invalid Path %s : path does not target a LWM2M object instance for %s", path,
node);
} else if (node.getId() != path.getObjectInstanceId()) {
childNode);
} else if (childNode.getId() != path.getObjectInstanceId()) {
return String.format(
"Invalid Path %s : path object instance id (%d) does not match LWM2M object instance id %d for %s",
path, path.getObjectInstanceId(), node.getId(), node);
path, path.getObjectInstanceId(), childNode.getId(), childNode);
}
} else if (node instanceof LwM2mResource) {
} else if (childNode instanceof LwM2mResource) {
if (!path.isResource()) {
return String.format("Invalid Path %s : path does not target a LWM2M resource for %s", path, node);
} else if (node.getId() != path.getResourceId()) {
return String.format("Invalid Path %s : path does not target a LWM2M resource for %s", path, childNode);
} else if (childNode.getId() != path.getResourceId()) {
return String.format(
"Invalid Path %s : path resource id (%d) does not match LWM2M resource id %d for %s", path,
path.getResourceId(), node.getId(), node);
path.getResourceId(), childNode.getId(), childNode);
}
} else if (node instanceof LwM2mResourceInstance) {
} else if (childNode instanceof LwM2mResourceInstance) {
if (!path.isResourceInstance()) {
return String.format("Invalid Path %s : path does not target a LWM2M resource instance for %s", path,
node);
} else if (node.getId() != path.getResourceInstanceId()) {
childNode);
} else if (childNode.getId() != path.getResourceInstanceId()) {
return String.format(
"Invalid Path %s : path resource instance id (%d) does not match LWM2M resource instance id %d for %s",
path, path.getResourceInstanceId(), node.getId(), node);
path, path.getResourceInstanceId(), childNode.getId(), childNode);
}
}
return null;
Expand Down
Expand Up @@ -29,9 +29,9 @@
* An Objects defines a grouping of Resources and may consist of multiple instances.
* </p>
*/
public class LwM2mObject implements LwM2mNode {
public class LwM2mObject implements LwM2mChildNode {

private int id;
private final int id;

private final Map<Integer, LwM2mObjectInstance> instances;

Expand Down
Expand Up @@ -29,7 +29,7 @@
/**
* An instance of {@link LwM2mObject}.
*/
public class LwM2mObjectInstance implements LwM2mNode {
public class LwM2mObjectInstance implements LwM2mChildNode {

/** Undefined instance Id */
public static final int UNDEFINED = -1;
Expand Down
Expand Up @@ -27,7 +27,7 @@
* A resource could be a {@link LwM2mSingleResource} or a {@link LwM2mMultipleResource}.
* </p>
*/
public interface LwM2mResource extends LwM2mNode {
public interface LwM2mResource extends LwM2mChildNode {

/**
* @return the type of the resource.
Expand Down
Expand Up @@ -26,7 +26,7 @@
/**
* An instance of {@link LwM2mMultipleResource}.
*/
public class LwM2mResourceInstance implements LwM2mNode {
public class LwM2mResourceInstance implements LwM2mChildNode {

private final int id;
private final Object value;
Expand Down
Expand Up @@ -16,6 +16,7 @@
package org.eclipse.leshan.core.request;

import org.eclipse.leshan.core.model.ResourceModel.Type;
import org.eclipse.leshan.core.node.LwM2mChildNode;
import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.node.LwM2mObject;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
Expand All @@ -30,7 +31,7 @@
public class BootstrapWriteRequest extends AbstractSimpleDownlinkRequest<BootstrapWriteResponse>
implements BootstrapDownlinkRequest<BootstrapWriteResponse> {

private final LwM2mNode node;
private final LwM2mChildNode node;
private final ContentFormat contentFormat;

public BootstrapWriteRequest(LwM2mPath target, LwM2mNode node, ContentFormat format) {
Expand Down Expand Up @@ -93,15 +94,15 @@ public BootstrapWriteRequest(LwM2mPath target, LwM2mNode node, ContentFormat for
}
}

this.node = node;
this.node = (LwM2mChildNode) node;
if (format == null) {
this.contentFormat = ContentFormat.TLV; // use TLV as default content type
} else {
this.contentFormat = format;
}
}

public LwM2mNode getNode() {
public LwM2mChildNode getNode() {
return node;
}

Expand Down
Expand Up @@ -21,6 +21,7 @@

import org.eclipse.leshan.core.link.Link;
import org.eclipse.leshan.core.model.ResourceModel.Type;
import org.eclipse.leshan.core.node.LwM2mChildNode;
import org.eclipse.leshan.core.node.LwM2mMultipleResource;
import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
Expand Down Expand Up @@ -55,7 +56,7 @@ public enum Mode {
UPDATE
}

private final LwM2mNode node;
private final LwM2mChildNode node;
private final ContentFormat contentFormat;
private final Mode mode;

Expand Down Expand Up @@ -464,7 +465,7 @@ public WriteRequest(Mode mode, ContentFormat format, LwM2mPath target, LwM2mNode
}
}

this.node = node;
this.node = (LwM2mChildNode) node;
if (format == null) {
this.contentFormat = ContentFormat.TLV; // use TLV as default content type
} else {
Expand All @@ -487,7 +488,7 @@ public boolean isPartialUpdateRequest() {
return mode == Mode.UPDATE;
}

public LwM2mNode getNode() {
public LwM2mChildNode getNode() {
return node;
}

Expand Down
Expand Up @@ -16,12 +16,13 @@
package org.eclipse.leshan.core.response;

import org.eclipse.leshan.core.ResponseCode;
import org.eclipse.leshan.core.node.LwM2mChildNode;
import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.request.exception.InvalidResponseException;

public class BootstrapReadResponse extends AbstractLwM2mResponse {

protected final LwM2mNode content;
protected final LwM2mChildNode content;

public BootstrapReadResponse(ResponseCode code, LwM2mNode content, String errorMessage) {
this(code, content, errorMessage, null);
Expand All @@ -33,8 +34,13 @@ public BootstrapReadResponse(ResponseCode code, LwM2mNode content, String errorM
if (ResponseCode.CONTENT.equals(code)) {
if (content == null)
throw new InvalidResponseException("Content is mandatory for successful response");

if (!(content instanceof LwM2mChildNode))
throw new InvalidResponseException("Invalid Content : node should be a LwM2mChildNode not a %s",
content.getClass().getSimpleName());
}
this.content = content;

this.content = (LwM2mChildNode) content;
}

@Override
Expand Down Expand Up @@ -63,7 +69,7 @@ public boolean isValid() {
*
* @return the value or <code>null</code> if the client returned an error response.
*/
public LwM2mNode getContent() {
public LwM2mChildNode getContent() {
return content;
}

Expand All @@ -77,7 +83,7 @@ public String toString() {

// Syntactic sugar static constructors :

public static BootstrapReadResponse success(LwM2mNode content) {
public static BootstrapReadResponse success(LwM2mChildNode content) {
return new BootstrapReadResponse(ResponseCode.CONTENT, content, null, null);
}

Expand Down
Expand Up @@ -20,6 +20,7 @@

import org.eclipse.leshan.core.ResponseCode;
import org.eclipse.leshan.core.model.ResourceModel.Type;
import org.eclipse.leshan.core.node.LwM2mChildNode;
import org.eclipse.leshan.core.node.LwM2mMultipleResource;
import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
Expand All @@ -29,7 +30,7 @@

public class ReadResponse extends AbstractLwM2mResponse {

protected final LwM2mNode content;
protected final LwM2mChildNode content;

public ReadResponse(ResponseCode code, LwM2mNode content, String errorMessage) {
this(code, content, errorMessage, null);
Expand All @@ -41,8 +42,12 @@ public ReadResponse(ResponseCode code, LwM2mNode content, String errorMessage, O
if (ResponseCode.CONTENT.equals(code)) {
if (content == null)
throw new InvalidResponseException("Content is mandatory for successful response");

if (!(content instanceof LwM2mChildNode))
throw new InvalidResponseException("Invalid Content : node should be a LwM2mChildNode not a %s",
content.getClass().getSimpleName());
}
this.content = content;
this.content = (LwM2mChildNode) content;
}

@Override
Expand Down Expand Up @@ -71,7 +76,7 @@ public boolean isValid() {
*
* @return the value or <code>null</code> if the client returned an error response.
*/
public LwM2mNode getContent() {
public LwM2mChildNode getContent() {
return content;
}

Expand Down
Expand Up @@ -46,7 +46,6 @@ public void should_getPathNodesMapForTimestamp_pick_specific_timestamp_nodes() {
// then
assertNotNull(tsNodesMap);
assertTrue(tsNodesMap.containsKey(new LwM2mPath("/0/0/1")));
assertEquals(1L, tsNodesMap.get(new LwM2mPath("/0/0/1")).getId());
}

@Test
Expand All @@ -60,7 +59,6 @@ public void should_getPathNodesMapForTimestamp_pick_null_timestamp_nodes() {
// then
assertNotNull(tsNodesMap);
assertTrue(tsNodesMap.containsKey(new LwM2mPath("/0/0/2")));
assertEquals(2L, tsNodesMap.get(new LwM2mPath("/0/0/2")).getId());
}

@Test
Expand All @@ -87,8 +85,6 @@ public void should_getNodes_returns_all_nodes_ignoring_timestamp() {
assertNotNull(tsNodesMap);
assertTrue(tsNodesMap.containsKey(new LwM2mPath("/0/0/1")));
assertTrue(tsNodesMap.containsKey(new LwM2mPath("/0/0/2")));
assertEquals(1L, tsNodesMap.get(new LwM2mPath("/0/0/1")).getId());
assertEquals(2L, tsNodesMap.get(new LwM2mPath("/0/0/2")).getId());
}

@Test
Expand Down
Expand Up @@ -33,6 +33,7 @@
import org.eclipse.leshan.client.servers.LwM2mServer;
import org.eclipse.leshan.core.endpoint.Protocol;
import org.eclipse.leshan.core.model.ResourceModel.Type;
import org.eclipse.leshan.core.node.LwM2mChildNode;
import org.eclipse.leshan.core.node.LwM2mNode;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
Expand Down Expand Up @@ -130,7 +131,7 @@ public void server_handle_multiple_timestamped_node(ContentFormat contentFormat,
Map<LwM2mPath, LwM2mNode> pathNodeMap = data.getNodesAt(ts);
assertThat(pathNodeMap).containsKey(getExamplePath());

LwM2mNode node = pathNodeMap.get(getExamplePath());
LwM2mChildNode node = (LwM2mChildNode) pathNodeMap.get(getExamplePath());
assertThat(node.getId()).isEqualTo(TestLwM2mId.FLOAT_VALUE);
assertThat(node).isInstanceOfSatisfying(LwM2mSingleResource.class,
n -> assertThat(n.getType()).isEqualTo(Type.FLOAT));
Expand Down

0 comments on commit 4fa2c80

Please sign in to comment.