<artifactId>sal-common-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common-impl</artifactId>
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.impl
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import java.util.Map
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import java.util.Map.Entry
+import java.util.HashSet
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+
+class DataUtils {
+
+ static def CompositeNode read(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+ val root = map.get(path);
+ val childs = map.getChilds(path);
+ if(root === null && childs.empty) {
+ return null;
+ }
+
+ return merge(path, root, childs);
+ }
+
+ static def CompositeNode merge(InstanceIdentifier path, CompositeNode node,
+ HashSet<Entry<InstanceIdentifier, CompositeNode>> entries) {
+ val it = new ArrayList<Node<?>>();
+ val qname = path.path.last.nodeType;
+ if (node != null) {
+ addAll(node.children);
+ }
+ for (entry : entries) {
+ val nesting = entry.key.path.size - path.path.size;
+ if (nesting === 1) {
+ add(entry.value);
+ }
+ }
+ return new CompositeNodeTOImpl(qname, null, it);
+ }
+
+ static def getChilds(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+ val it = new HashSet<Entry<InstanceIdentifier, CompositeNode>>();
+ for (entry : map.entrySet) {
+ if (path.contains(entry.key)) {
+ add(entry);
+ }
+ }
+ return it;
+ }
+
+}
import java.util.Collections
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import static extension org.opendaylight.controller.sal.dom.broker.impl.DataUtils.*;
class HashMapDataStore //
implements //
val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
override readConfigurationData(InstanceIdentifier path) {
- configuration.get(path);
+ configuration.read(path);
}
override readOperationalData(InstanceIdentifier path) {
- operational.get(path);
+ operational.read(path);
}
+
+
+
override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
return new HashMapDataStoreTransaction(modification, this);
--- /dev/null
+package org.opendaylight.controller.sal.rest.api;
+
+public class Draft02 {
+ public static class MediaTypes {
+ public static final String API = "application/yang.api";
+ public static final String DATASTORE = "application/yang.datastore";
+ public static final String DATA = "application/yang.data";
+ public static final String OPERATION = "application/yang.operation";
+ public static final String PATCH = "application/yang.patch";
+ public static final String PATCH_STATUS = "application/yang.patch-status";
+ public static final String STREAM = "application/yang.stream";
+ }
+
+ public static class Paths {
+
+ }
+}
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
/**
* Section 5 for details on each URI.
* <ul>
* <li><b>/restconf</b> - {@link #getRoot()}
- * <ul><li><b>/datastore</b> - {@link #readAllData()}
+ * <ul><li><b>/config</b>
+ * <li><b>/operational</b> - {@link #readAllData()} - Added in Draft02
+ * <li><b>/datastore</b> - {@link #readAllData()}
* <ul>
* <li>/(top-level-data-nodes) (config=true or false)
* </ul>
* </ul>
*/
@Path("/")
-public interface RestconfService {
+public interface RestconfService extends RestconfServiceLegacy {
public static final String XML = "+xml";
public static final String JSON = "+json";
@GET
public Object getRoot();
+
@GET
- @Path("/datastore")
+ @Path("/modules")
@Produces({API+JSON,API+XML})
- public Object readAllData();
+ public StructuredData getModules();
+ @POST
+ @Path("/operations/{identifier}")
+ @Produces({Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML,API+JSON,API+XML})
+ public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+
+
@GET
- @Path("/datastore/{identifier:.+}")
- @Produces({API+JSON,API+XML})
- public StructuredData readData(@PathParam("identifier") String identifier);
+ @Path("/config/{identifier:.+}")
+ @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+ public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
+
+
@PUT
- @Path("/datastore/{identifier:.+}")
+ @Path("/config/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public Object createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+ public RpcResult<TransactionStatus> createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
@POST
- @Path("/datastore/{identifier:.+}")
+ @Path("/config/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public Object updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+ public RpcResult<TransactionStatus> updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
@GET
- @Path("/modules")
+ @Path("/operational/{identifier:.+}")
+ @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+ public StructuredData readOperationalData(@PathParam("identifier") String identifier);
+
+ @PUT
+ @Path("/operational/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public Object getModules();
+ public RpcResult<TransactionStatus> createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
@POST
- @Path("/operations/{identifier}")
+ @Path("/operational/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+ public RpcResult<TransactionStatus> updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
+
+
}
--- /dev/null
+package org.opendaylight.controller.sal.rest.api;
+
+import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface RestconfServiceLegacy {
+
+ public static final String XML = "+xml";
+ public static final String JSON = "+json";
+
+ @Deprecated
+ @GET
+ @Path("/datastore")
+ @Produces({API+JSON,API+XML})
+ public StructuredData readAllData();
+
+ @Deprecated
+ @GET
+ @Path("/datastore/{identifier:.+}")
+ @Produces({API+JSON,API+XML})
+ public StructuredData readData(@PathParam("identifier") String identifier);
+
+ @Deprecated
+ @PUT
+ @Path("/datastore/{identifier:.+}")
+ @Produces({API+JSON,API+XML})
+ public RpcResult<TransactionStatus> createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+ @Deprecated
+ @POST
+ @Path("/datastore/{identifier:.+}")
+ @Produces({API+JSON,API+XML})
+ public RpcResult<TransactionStatus> updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+}
return future.get;
}
- def commitConfigurationDataUpdate(InstanceIdentifier path, CompositeNode payload) {
+ def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
val transaction = dataService.beginTransaction;
transaction.putConfigurationData(path, payload);
return transaction.commit()
}
- def commitConfigurationDataCreate(InstanceIdentifier path, CompositeNode payload) {
+ def commitOperationalDataPut(InstanceIdentifier path, CompositeNode payload) {
val transaction = dataService.beginTransaction;
- transaction.putConfigurationData(path, payload);
+ transaction.putOperationalData(path, payload);
return transaction.commit()
}
import static com.google.common.base.Preconditions.*
import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import java.util.concurrent.ConcurrentHashMap
class ControllerContext implements SchemaServiceListener {
private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
+ private val Map<QName,RpcDefinition> qnameToRpc = new ConcurrentHashMap();
+
private new() {
if (INSTANCE != null) {
}
}
- public def QName toRpcQName(String name) {
+ public def QName toQName(String name) {
+ val module = name.toModuleName;
+ val node = name.toNodeName;
+ val namespace = moduleNameToUri.get(module);
+ return new QName(namespace,null,node);
}
override onGlobalContextUpdated(SchemaContext context) {
this.schemas = context;
+ for(operation : context.operations) {
+ val qname = new QName(operation.QName.namespace,null,operation.QName.localName);
+ qnameToRpc.put(qname,operation);
+ }
+ }
+
+ def ContainerSchemaNode getRpcOutputSchema(QName name) {
+ qnameToRpc.get(name)?.output;
}
}
override readAllData() {
// return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ throw new UnsupportedOperationException("Reading all data is currently not supported.")
}
override getModules() {
}
override getRoot() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
-
+ return null;
}
override readData(String identifier) {
}
override createConfigurationData(String identifier, CompositeNode payload) {
-// return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
}
override updateConfigurationData(String identifier, CompositeNode payload) {
-// return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
}
override invokeRpc(String identifier, CompositeNode payload) {
- val rpcResult = broker.invokeRpc(identifier.toRpcQName, payload);
- return new StructuredData(rpcResult.result, identifier.toInstanceIdentifier.getSchemaNode)
+ val rpc = identifier.toQName;
+ val rpcResult = broker.invokeRpc(rpc, payload);
+ val schema = controllerContext.getRpcOutputSchema(rpc);
+ return new StructuredData(rpcResult.result, schema);
+ }
+
+ override readConfigurationData(String identifier) {
+ val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+ val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+ return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+ }
+
+ override readOperationalData(String identifier) {
+ val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+ val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+ return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+ }
+
+ override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
+ updateConfigurationData(identifier,payload);
+ }
+
+ override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
+ createConfigurationData(identifier,payload);
+ }
+
+ override createOperationalData(String identifier, CompositeNode payload) {
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+ }
+
+ override updateOperationalData(String identifier, CompositeNode payload) {
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
}
}