Merge changes Ifdaf681e,Ifc13df7c
authorEd Warnicke <eaw@cisco.com>
Mon, 11 Nov 2013 14:09:05 +0000 (14:09 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 11 Nov 2013 14:09:05 +0000 (14:09 +0000)
* changes:
  Fixed merge of entries in mock data store
  Added paths and mediatypes from Restconf draft 02

opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend

index f92d86af91b46ba1f072fac794511e07f26ec97b..62dbe16e4135de42001f6fde721799128b8dbebd 100644 (file)
             <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>
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataUtils.xtend
new file mode 100644 (file)
index 0000000..1a2f947
--- /dev/null
@@ -0,0 +1,50 @@
+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;
+    }
+
+}
index 404842c1dcea4875fd71818b620dfea8c0f0d49b..7d57819cbf0ac3a1775c4eedc026719740a8fce7 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.sal.common.util.Rpcs
 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 //
@@ -20,12 +21,15 @@ DataReader<InstanceIdentifier, CompositeNode>, DataCommitHandler<InstanceIdentif
     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);
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/Draft02.java
new file mode 100644 (file)
index 0000000..70b2cf5
--- /dev/null
@@ -0,0 +1,17 @@
+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 {
+        
+    }
+}
index b8cb2292542b8da4ecf7f8573d6b578a47ff3810..c36a79c5d901093ad3bf79d1a4a354ebcf161209 100644 (file)
@@ -16,7 +16,9 @@ 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;
 
 /**
@@ -25,7 +27,9 @@ 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>
@@ -45,7 +49,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  *     </ul>
  */
 @Path("/")
-public interface RestconfService {
+public interface RestconfService extends RestconfServiceLegacy {
 
     public static final String XML = "+xml";
     public static final String JSON = "+json";
@@ -53,33 +57,49 @@ public interface RestconfService {
     @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);
+
+    
 }
diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfServiceLegacy.java
new file mode 100644 (file)
index 0000000..6683fd1
--- /dev/null
@@ -0,0 +1,46 @@
+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);
+
+}
index 8e18661db6ecdfcc65d822dff5bf1e4c115c0b96..3c31c5a313ec0b45a9a8390729638331d4a7a7a0 100644 (file)
@@ -42,15 +42,15 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
         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()
     }
     
index 2b3a3042c2ce9119c9ee9d0176dcf88ed52807cb..400850103d7be35f72beeb39088a1618a23feff5 100644 (file)
@@ -25,6 +25,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext
 
 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 {
 
@@ -37,6 +39,8 @@ 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) {
@@ -272,11 +276,23 @@ class ControllerContext implements SchemaServiceListener {
         }
     }
 
-    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;
     }
 
 }
index fc0dd1017fea6fbb9e77cd5f3b5a84d616b9e58f..31fbe8ec876876b0d677ffaa90df95fddbdfa91a 100644 (file)
@@ -25,7 +25,7 @@ class RestconfImpl implements RestconfService {
 
     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() {
@@ -33,8 +33,7 @@ class RestconfImpl implements RestconfService {
     }
 
     override getRoot() {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-
+        return null;
     }
 
     override readData(String identifier) {
@@ -44,18 +43,50 @@ class RestconfImpl implements RestconfService {
     }
 
     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();
     }
 
 }