Skip to content

Commit

Permalink
#597:add a way to do atomic read/write/observe at instance enabler level
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Jan 16, 2019
1 parent a94d9e2 commit e14092a
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.leshan.client.request.ServerIdentity;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.response.ExecuteResponse;
import org.eclipse.leshan.core.response.ObserveResponse;
Expand All @@ -31,8 +35,9 @@

public class BaseInstanceEnabler implements LwM2mInstanceEnabler {

private List<ResourceChangedListener> listeners = new ArrayList<>();
private Integer id = null;
protected List<ResourceChangedListener> listeners = new ArrayList<>();
protected Integer id = null;
protected ObjectModel model;

public BaseInstanceEnabler() {
}
Expand All @@ -51,6 +56,15 @@ public Integer getId() {
return id;
}

@Override
public void setModel(ObjectModel model) {
this.model = model;
}

public ObjectModel getModel() {
return model;
}

@Override
public void addResourceChangedListener(ResourceChangedListener listener) {
listeners.add(listener);
Expand All @@ -67,11 +81,49 @@ public void fireResourcesChange(int... resourceIds) {
}
}

@Override
public ReadResponse read(ServerIdentity identity) {
List<LwM2mResource> resources = new ArrayList<>();
for (ResourceModel resourceModel : model.resources.values()) {
// check, if internal request (SYSTEM) or readable
if (identity.isSystem() || resourceModel.operations.isReadable()) {
ReadResponse response = read(identity, resourceModel.id);
if (response.isSuccess() && response.getContent() instanceof LwM2mResource)
resources.add((LwM2mResource) response.getContent());
}
}
return ReadResponse.success(new LwM2mObjectInstance(id, resources));
}

@Override
public ReadResponse read(ServerIdentity identity, int resourceid) {
return ReadResponse.notFound();
}

@Override
public WriteResponse write(ServerIdentity identity, boolean replace, LwM2mObjectInstance value) {
Map<Integer, LwM2mResource> resourcesToWrite = new HashMap<>(value.getResources());

if (replace) {
// REPLACE
for (ResourceModel resourceModel : model.resources.values()) {
if (!identity.isLwm2mServer() || resourceModel.operations.isWritable()) {
LwM2mResource writeResource = resourcesToWrite.remove(resourceModel.id);
if (null != writeResource) {
write(identity, resourceModel.id, writeResource);
} else {
reset(resourceModel.id);
}
}
}
}
// UPDATE and resources currently not in the model
for (LwM2mResource resource : resourcesToWrite.values()) {
write(identity, resource.getId(), resource);
}
return WriteResponse.success();
}

@Override
public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
return WriteResponse.notFound();
Expand All @@ -82,6 +134,14 @@ public ExecuteResponse execute(ServerIdentity identity, int resourceid, String p
return ExecuteResponse.notFound();
}

@Override
public ObserveResponse observe(ServerIdentity identity) {
// Perform a read by default
ReadResponse readResponse = this.read(identity);
return new ObserveResponse(readResponse.getCode(), readResponse.getContent(), null, null,
readResponse.getErrorMessage());
}

@Override
public ObserveResponse observe(ServerIdentity identity, int resourceid) {
// Perform a read by default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public LwM2mInstanceEnabler create(ObjectModel model, Integer id, Collection<Int
}

// create new instance
LwM2mInstanceEnabler instance = create(model);
LwM2mInstanceEnabler instance = create();

// set id if not already done
if (instance.getId() == null) {
Expand All @@ -42,6 +42,9 @@ public LwM2mInstanceEnabler create(ObjectModel model, Integer id, Collection<Int
}
}

// set model
instance.setModel(model);

return instance;
}

Expand All @@ -58,10 +61,9 @@ protected int getNewInstanceId(Collection<Integer> alreadyUsedIdentifier) {
/**
* Create a new instance enabler.
*
* @param model of this instance (CAN NOT be null).
* @return the new instance enabler
*/
public abstract LwM2mInstanceEnabler create(ObjectModel model);
public abstract LwM2mInstanceEnabler create();

public static int generateNewInstanceId(Collection<Integer> alreadyUsedIdentifier) {
if (alreadyUsedIdentifier.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

import org.eclipse.leshan.client.request.ServerIdentity;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mResource;
import org.eclipse.leshan.core.request.WriteRequest.Mode;
import org.eclipse.leshan.core.response.ExecuteResponse;
import org.eclipse.leshan.core.response.ObserveResponse;
import org.eclipse.leshan.core.response.ReadResponse;
Expand Down Expand Up @@ -61,6 +63,14 @@ public interface LwM2mInstanceEnabler {
*/
void setId(int id);

/**
* Set the model of this instance. It should be called only by
* {@link LwM2mInstanceEnablerFactory#create(ObjectModel, Integer, java.util.Collection)}.
*
* @param model the model of this instance
*/
void setModel(ObjectModel model);

/**
* Adds a callback handler that gets notified about changes to any of this LWM2M object instance's resources.
*
Expand All @@ -75,6 +85,17 @@ public interface LwM2mInstanceEnabler {
*/
void removeResourceChangedListener(ResourceChangedListener listener);

/**
* Gets values of all readable resources of this instance.
*
* @param identity the identity of the requester. This could be an internal call in this case
* <code> identity == ServerIdentity.SYSTEM</code>.
*
* @return a success response with an {@link LwM2mObjectInstance} as content or a failure response with optional
* explanation message.
*/
ReadResponse read(ServerIdentity identity);

/**
* Gets the current value of one of this LWM2M object instance's resources.
*
Expand All @@ -87,6 +108,19 @@ public interface LwM2mInstanceEnabler {
*/
ReadResponse read(ServerIdentity identity, int resourceId);

/**
* Sets all resources of this LWM2M object instance.
*
* @param identity the identity of the requester. This could be an internal call in this case
* <code> identity == ServerIdentity.SYSTEM</code>.
* @param replace if replace is true a {@link Mode#REPLACE} should be done, else {@link Mode#UPDATE} should be done.
* @param value all the resources to be written.
* @return the response object representing the outcome of the operation. An implementation should set the result's
* {@link WriteResponse#getCode() response code} to either reflect the success or reason for failure to set
* the value.
*/
WriteResponse write(ServerIdentity identity, boolean replace, LwM2mObjectInstance value);

/**
* Sets the value of one of this LWM2M object instance's resources.
*
Expand All @@ -113,6 +147,16 @@ public interface LwM2mInstanceEnabler {
*/
ExecuteResponse execute(ServerIdentity identity, int resourceid, String params);

/**
* Performs an observe register the whole LWM2M object instance.
*
* @param identity the identity of the requester. This could be an internal call in this case
* <code> identity == ServerIdentity.SYSTEM</code>.
* @return a success response with an {@link LwM2mObjectInstance} as content or a failure response with optional
* explanation message.
*/
ObserveResponse observe(ServerIdentity identity);

/**
* Performs an observe register on one of this LWM2M object instance's resources.
*
Expand All @@ -135,5 +179,4 @@ public interface LwM2mInstanceEnabler {
* @param resourceId the ID of the resource to be reseted
*/
void reset(int resourceId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@
import java.util.Map.Entry;

import org.eclipse.leshan.LwM2mId;
import org.eclipse.leshan.ResponseCode;
import org.eclipse.leshan.client.request.ServerIdentity;
import org.eclipse.leshan.client.servers.ServersInfoExtractor;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.model.ResourceModel;
import org.eclipse.leshan.core.node.LwM2mObject;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mPath;
Expand Down Expand Up @@ -142,8 +140,11 @@ protected ReadResponse doRead(ServerIdentity identity, ReadRequest request) {
// Manage Object case
if (path.isObject()) {
List<LwM2mObjectInstance> lwM2mObjectInstances = new ArrayList<>();
for (Entry<Integer, LwM2mInstanceEnabler> entry : instances.entrySet()) {
lwM2mObjectInstances.add(getLwM2mObjectInstance(entry.getKey(), entry.getValue(), identity, false));
for (LwM2mInstanceEnabler instance : instances.values()) {
ReadResponse response = instance.read(identity);
if (response.isSuccess()) {
lwM2mObjectInstances.add((LwM2mObjectInstance) response.getContent());
}
}
return ReadResponse.success(new LwM2mObject(getId(), lwM2mObjectInstances));
}
Expand All @@ -154,7 +155,7 @@ protected ReadResponse doRead(ServerIdentity identity, ReadRequest request) {
return ReadResponse.notFound();

if (path.getResourceId() == null) {
return ReadResponse.success(getLwM2mObjectInstance(path.getObjectInstanceId(), instance, identity, false));
return instance.read(identity);
}

// Manage Resource case
Expand All @@ -168,8 +169,11 @@ protected ObserveResponse doObserve(final ServerIdentity identity, final Observe
// Manage Object case
if (path.isObject()) {
List<LwM2mObjectInstance> lwM2mObjectInstances = new ArrayList<>();
for (Entry<Integer, LwM2mInstanceEnabler> entry : instances.entrySet()) {
lwM2mObjectInstances.add(getLwM2mObjectInstance(entry.getKey(), entry.getValue(), identity, true));
for (LwM2mInstanceEnabler instance : instances.values()) {
ReadResponse response = instance.observe(identity);
if (response.isSuccess()) {
lwM2mObjectInstances.add((LwM2mObjectInstance) response.getContent());
}
}
return ObserveResponse.success(new LwM2mObject(getId(), lwM2mObjectInstances));
}
Expand All @@ -180,34 +184,13 @@ protected ObserveResponse doObserve(final ServerIdentity identity, final Observe
return ObserveResponse.notFound();

if (path.getResourceId() == null) {
return ObserveResponse
.success(getLwM2mObjectInstance(path.getObjectInstanceId(), instance, identity, true));
return instance.observe(identity);
}

// Manage Resource case
return instance.observe(identity, path.getResourceId());
}

LwM2mObjectInstance getLwM2mObjectInstance(int instanceid, LwM2mInstanceEnabler instance, ServerIdentity identity,
boolean observe) {
List<LwM2mResource> resources = new ArrayList<>();
for (ResourceModel resourceModel : getObjectModel().resources.values()) {
// check, if internal request (SYSTEM) or readable
if (identity.isSystem() || resourceModel.operations.isReadable()) {
if (observe) {
ObserveResponse response = instance.observe(identity, resourceModel.id);
if (response.getCode() == ResponseCode.CONTENT && response.getContent() instanceof LwM2mResource)
resources.add((LwM2mResource) response.getContent());
} else {
ReadResponse response = instance.read(identity, resourceModel.id);
if (response.getCode() == ResponseCode.CONTENT && response.getContent() instanceof LwM2mResource)
resources.add((LwM2mResource) response.getContent());
}
}
}
return new LwM2mObjectInstance(instanceid, resources);
}

@Override
protected WriteResponse doWrite(ServerIdentity identity, WriteRequest request) {
LwM2mPath path = request.getPath();
Expand All @@ -218,27 +201,7 @@ protected WriteResponse doWrite(ServerIdentity identity, WriteRequest request) {
return WriteResponse.notFound();

if (path.isObjectInstance()) {
// instance write
Map<Integer, LwM2mResource> writeResources = ((LwM2mObjectInstance) request.getNode()).getResources();
if (request.isReplaceRequest()) {
// REPLACE
writeResources = new HashMap<>(writeResources); // make them modifiable
for (ResourceModel resourceModel : getObjectModel().resources.values()) {
if (!identity.isLwm2mServer() || resourceModel.operations.isWritable()) {
LwM2mResource writeResource = writeResources.remove(resourceModel.id);
if (null != writeResource) {
instance.write(identity, resourceModel.id, writeResource);
} else {
instance.reset(resourceModel.id);
}
}
}
}
// UPDATE and resources currently not in the model
for (LwM2mResource resource : writeResources.values()) {
instance.write(identity, resource.getId(), resource);
}
return WriteResponse.success();
return instance.write(identity, request.isReplaceRequest(), (LwM2mObjectInstance) request.getNode());
}

// Manage Resource case
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ public class ObjectsInitializer {

protected LwM2mInstanceEnablerFactory defaultFactory = new BaseInstanceEnablerFactory() {
@Override
public LwM2mInstanceEnabler create(ObjectModel model) {
SimpleInstanceEnabler simpleInstanceEnabler = new SimpleInstanceEnabler();
simpleInstanceEnabler.setObjectModel(model);
return simpleInstanceEnabler;
public LwM2mInstanceEnabler create() {
return new SimpleInstanceEnabler();
}
};

Expand Down Expand Up @@ -167,6 +165,7 @@ protected ObjectEnabler createNodeEnabler(ObjectModel objectModel) {
int id = BaseInstanceEnablerFactory.generateNewInstanceId(instances.keySet());
instance.setId(id);
}
instance.setModel(objectModel);
instances.put(instance.getId(), instance);
}
return new ObjectEnabler(objectModel.id, objectModel, instances, getFactoryFor(objectModel),
Expand Down Expand Up @@ -198,7 +197,7 @@ protected LwM2mInstanceEnabler[] createInstances(ObjectModel objectModel) {
protected LwM2mInstanceEnablerFactory getClassFactory(final Class<? extends LwM2mInstanceEnabler> clazz) {
LwM2mInstanceEnablerFactory factory = new BaseInstanceEnablerFactory() {
@Override
public LwM2mInstanceEnabler create(ObjectModel model) {
public LwM2mInstanceEnabler create() {
try {
return clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public class SimpleInstanceEnabler extends BaseInstanceEnabler {

private static Logger LOG = LoggerFactory.getLogger(SimpleInstanceEnabler.class);
protected Map<Integer, LwM2mResource> resources = new HashMap<>();
protected ObjectModel objectModel;

public SimpleInstanceEnabler() {
}
Expand All @@ -65,7 +64,7 @@ public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResourc

@Override
public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
if (objectModel.resources.containsKey(resourceid)) {
if (getModel().resources.containsKey(resourceid)) {
LOG.info("Executing resource [{}] with params [{}]", resourceid, params);
return ExecuteResponse.success();
} else {
Expand All @@ -78,8 +77,9 @@ public void reset(int resourceid) {
resources.remove(resourceid);
}

public void setObjectModel(ObjectModel objectModel) {
this.objectModel = objectModel;
@Override
public void setModel(ObjectModel objectModel) {
super.setModel(objectModel);

// initialize resources
for (ResourceModel resourceModel : objectModel.resources.values()) {
Expand Down
Loading

0 comments on commit e14092a

Please sign in to comment.