Solved bugs and added tests in sal-rest-connector 57/2157/3
authormsunal <msunal@cisco.com>
Fri, 25 Oct 2013 09:18:30 +0000 (11:18 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 29 Oct 2013 11:31:06 +0000 (11:31 +0000)
- solved bugs in ControllerContext
- added tests
- formatting

Change-Id: Ia552ec3aa6a8e4949aedfc01f8386dbc6875a73f
Signed-off-by: Martin Sunal <msunal@cisco.com>
17 files changed:
opendaylight/md-sal/sal-rest-connector/pom.xml
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/InstanceIdWithSchemaNode.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ControllerContextTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/JsonMapperTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfImplTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/testData.json [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/testData.json with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/testData.xml [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/testData.xml with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/yangs/ex-vlan.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/ex-vlan.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/yangs/iana-if-type.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/iana-if-type.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/yangs/ietf-interfaces@2013-07-04.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/ietf-interfaces@2013-07-04.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/full-versions/yangs/ietf-yang-types@2013-05-16.yang [moved from opendaylight/md-sal/sal-rest-connector/src/test/resources/ietf-yang-types@2013-05-16.yang with 100% similarity]
opendaylight/md-sal/sal-rest-connector/src/test/resources/parts/ietf-interfaces_interfaces.xml [new file with mode: 0644]

index b28e9677b6897f30b163525b897bd027fbfc783e..24ac2467f04cdb418e0ff8cb8546295bb3c306fc 100644 (file)
       <groupId>org.eclipse.xtend</groupId>
       <artifactId>org.eclipse.xtend.lib</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.jboss.resteasy</groupId>
       <artifactId>jaxrs-api</artifactId>
       <version>3.0.4.Final</version>
       <scope>provided</scope>
     </dependency>
+    
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <version>1.0.9</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-parser-impl</artifactId>
+      <version>${yang.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-impl</artifactId>
+      <version>${yang.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
index e4cff4d6b14d54c93a80509d70fd386fc8477018..07cd4a846b211d68a1643081da667768a81e3a93 100644 (file)
@@ -12,10 +12,10 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
 
     @Property
     private ConsumerSession context;
-    
+
     @Property
     private DataBrokerService dataService;
-    
+
     override readConfigurationData(InstanceIdentifier path) {
         return dataService.readConfigurationData(path);
     }
@@ -23,22 +23,22 @@ class BrokerFacade implements DataReader<InstanceIdentifier, CompositeNode> {
     override readOperationalData(InstanceIdentifier path) {
         return dataService.readOperationalData(path);
     }
-    
+
     def RpcResult<CompositeNode> invokeRpc(QName type, CompositeNode payload) {
         val future = context.rpc(type, payload);
         return future.get;
     }
-    
+
     def commitConfigurationDataUpdate(InstanceIdentifier path, CompositeNode payload) {
         val transaction = dataService.beginTransaction;
         transaction.putConfigurationData(path, payload);
         return transaction.commit()
     }
-    
+
     def commitConfigurationDataCreate(InstanceIdentifier path, CompositeNode payload) {
         val transaction = dataService.beginTransaction;
         transaction.putConfigurationData(path, payload);
         return transaction.commit()
     }
-    
+
 }
index 49b997fa50f5b75767dc368923cf3c4b159ac3c6..419ca50ee995a032e5a63b3dc7ea1f50d79ba50e 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 
 import static com.google.common.base.Preconditions.*
+import java.util.Date
 
 class ControllerContext {
 
@@ -36,17 +37,35 @@ class ControllerContext {
     public def InstanceIdWithSchemaNode toInstanceIdentifier(String restconfInstance) {
         val ret = InstanceIdentifier.builder();
         val pathArgs = restconfInstance.split("/");
+        if (pathArgs.empty) {
+            return null;
+        }
         val schemaNode = ret.collectPathArguments(pathArgs, restconfInstance.findModule);
         new InstanceIdWithSchemaNode(ret.toInstance, schemaNode)
     }
-    
+
     def findModule(String restconfInstance) {
+        checkNotNull(restconfInstance);
         val pathArgs = restconfInstance.split("/");
-        val first = pathArgs.get(0);
-        val startModule = first.toModuleName();
-        val module = schemas.findModuleByNamespace(moduleNameToUri.get(startModule));
-        checkArgument(module.size == 1); // Only one version supported now
-        module.iterator.next
+        if (pathArgs.empty) {
+            return null;
+        }
+        val modulWithFirstYangStatement = pathArgs.filter[s|s.contains(":")].head
+        val startModule = modulWithFirstYangStatement.toModuleName();
+        schemas.getLatestModule(startModule)
+    }
+
+    private def getLatestModule(SchemaContext schema, String moduleName) {
+        checkNotNull(schema)
+        checkArgument(moduleName != null && !moduleName.empty)
+        val modules = schema.modules.filter[m|m.name == moduleName]
+        var latestModule = modules.head
+        for (module : modules) {
+            if (module.revision.after(latestModule.revision)) {
+                latestModule = module
+            }
+        }
+        return latestModule
     }
 
     def String toFullRestconfIdentifier(InstanceIdentifier path) {
@@ -137,30 +156,27 @@ class ControllerContext {
         return URLEncoder.encode(object.toString)
     }
 
-    def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings, DataNodeContainer parentNode) {
+    def DataSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
+        DataNodeContainer parentNode) {
         checkNotNull(strings)
-        if (strings.length == 0) {
-            return null;
+        if (strings.empty) {
+            return parentNode as DataSchemaNode;
         }
-        val nodeRef = strings.get(0);
+        val nodeRef = strings.head;
 
         //val moduleName = nodeRef.toModuleName();
         val nodeName = nodeRef.toNodeName();
-        val naiveTargetNode = parentNode.getDataChildByName(nodeName);
-
-        //var URI namespace;
-        var DataSchemaNode targetNode = naiveTargetNode;
+        val targetNode = parentNode.getDataChildByName(nodeName);
+        if (targetNode == null) {
+            return null
+        }
 
-        /*if(moduleName !== null) {
-            namespace = moduleNameToUri.get(moduleName);
-            
-        }*/
         // Number of consumed elements
         var consumed = 1;
         if (targetNode instanceof ListSchemaNode) {
             val listNode = targetNode as ListSchemaNode;
             val keysSize = listNode.keyDefinition.size
-            val uriKeyValues = strings.subList(1, keysSize);
+            val uriKeyValues = strings.subList(consumed, consumed + keysSize);
             val keyValues = new HashMap<QName, Object>();
             var i = 0;
             for (key : listNode.keyDefinition) {
@@ -176,11 +192,11 @@ class ControllerContext {
             builder.node(targetNode.QName);
         }
         if (targetNode instanceof DataNodeContainer) {
-            val remaining = strings.subList(consumed, strings.length - 1);
+            val remaining = strings.subList(consumed, strings.length);
             val result = builder.collectPathArguments(remaining, targetNode as DataNodeContainer);
             return result
         }
-        
+
         return targetNode
     }
 
@@ -193,6 +209,7 @@ class ControllerContext {
     }
 
     def String toModuleName(String str) {
+        checkNotNull(str)
         if (str.contains(":")) {
             val args = str.split(":");
             checkArgument(args.size === 2);
@@ -211,9 +228,7 @@ class ControllerContext {
             return str;
         }
     }
-    
+
     public def QName toRpcQName(String name) {
-        
-        
     }
 }
index dd03b7846228215cc29cf627f27c716cacd52654..ad0654af785bd13ac690409723ac45d0e55f22e9 100644 (file)
@@ -4,10 +4,10 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
 public class InstanceIdWithSchemaNode {
-    
+
     private final InstanceIdentifier instanceIdentifier;
     private final DataSchemaNode schemaNode;
-    
+
     public InstanceIdWithSchemaNode(InstanceIdentifier instanceIdentifier, DataSchemaNode schemaNode) {
         this.instanceIdentifier = instanceIdentifier;
         this.schemaNode = schemaNode;
@@ -20,5 +20,5 @@ public class InstanceIdWithSchemaNode {
     public DataSchemaNode getSchemaNode() {
         return schemaNode;
     }
-    
+
 }
index f75c12dc7e29a6151578e77241ba0a96dbc0e106..0b0ebc592259b5c89a8fb29ff9a2c9026b9d95a9 100644 (file)
@@ -6,58 +6,56 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import static com.google.common.base.Preconditions.*
 
 class RestconfImpl implements RestconfService {
-    
+
     @Property
     BrokerFacade broker
-    
+
     @Property
     extension ControllerContext controllerContext
-    
+
     val JsonMapper jsonMapper = new JsonMapper;
-    
+
     def init(SchemaService schemaService) {
         checkState(broker !== null)
         checkState(controllerContext !== null)
         checkState(schemaService !== null)
         controllerContext.schemas = schemaService.globalContext
     }
-    
+
     override readAllData() {
         return broker.readOperationalData("".removePrefixes.toInstanceIdentifier.getInstanceIdentifier);
     }
-    
-    
+
     override getModules() {
         throw new UnsupportedOperationException("TODO: auto-generated method stub")
     }
-    
+
     override getRoot() {
         throw new UnsupportedOperationException("TODO: auto-generated method stub")
-        
+
     }
-    
+
     override readData(String identifier) {
         val instanceIdentifierWithSchemaNode = identifier.removePrefixes.toInstanceIdentifier
-        val data =  broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+        val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
         jsonMapper.convert(instanceIdentifierWithSchemaNode.getSchemaNode, data)
     }
-    
+
     override createConfigurationData(String identifier, CompositeNode payload) {
         return broker.commitConfigurationDataCreate(identifier.removePrefixes.toInstanceIdentifier.getInstanceIdentifier, payload);
     }
-    
-    
+
     override updateConfigurationData(String identifier, CompositeNode payload) {
         return broker.commitConfigurationDataCreate(identifier.removePrefixes.toInstanceIdentifier.getInstanceIdentifier, payload);
     }
-    
+
     override invokeRpc(String identifier, CompositeNode payload) {
         val rpcResult = broker.invokeRpc(identifier.removePrefixes.toRpcQName, payload);
         jsonMapper.convert(identifier.removePrefixes.toInstanceIdentifier.getSchemaNode, rpcResult.result);
     }
-    
+
     private def String removePrefixes(String path) {
         return path;
     }
-    
-}
\ No newline at end of file
+
+}
index 3dc181b826bc5b9a17be4caccf2fd768832d1889..8f821410c60e190d7e2788544817e6e33cb9aad3 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+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;
@@ -14,11 +16,8 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
-import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.*;
-
 /**
  *   The URI hierarchy for the RESTCONF resources consists of an entry
  *   point container, 3 top-level resources, and 1 field.  Refer to
@@ -49,37 +48,35 @@ public interface RestconfService {
 
     public static final String XML = "+xml";
     public static final String JSON = "+json";
-    
+
     @GET
     public Object getRoot();
-    
+
     @GET
     @Path("/datastore")
     @Produces({API+JSON,API+XML})
     public Object readAllData();
-    
+
     @GET
     @Path("/datastore/{identifier}")
     @Produces({API+XML})
     public Object readData(@PathParam("identifier") String identifier);
-    
+
     @PUT
     @Path("/datastore/{identifier}")
     @Produces({API+XML})
     public Object createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
-    
+
     @POST
     @Path("/datastore/{identifier}")
     @Produces({API+XML})
     public Object updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
-    
-    
-    
+
     @GET
     @Path("/modules")
     @Produces(API+XML)
     public Object getModules();
-    
+
     @POST
     @Path("/operations/{identifier}")
     @Produces(API+XML)
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ControllerContextTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/ControllerContextTest.java
new file mode 100644 (file)
index 0000000..9916278
--- /dev/null
@@ -0,0 +1,35 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.FileNotFoundException;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class ControllerContextTest {
+
+    private static final ControllerContext controllerContext = new ControllerContext();
+
+    @BeforeClass
+    public static void init() throws FileNotFoundException {
+        Set<Module> allModules = TestUtils.loadModules(ControllerContextTest.class.getResource("/full-versions/yangs").getPath());
+        assertEquals(4, allModules.size());
+        SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+        controllerContext.setSchemas(schemaContext);
+    }
+
+    @Test
+    public void testToInstanceIdentifierList() throws FileNotFoundException {
+        InstanceIdWithSchemaNode instanceIdentifier = controllerContext.toInstanceIdentifier("ietf-interfaces:interfaces/interface/foo");
+        DataSchemaNode schemaNode = instanceIdentifier.getSchemaNode();
+        assertEquals(schemaNode.getQName().getLocalName(), "interface");
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/JsonMapperTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/JsonMapperTest.java
new file mode 100644 (file)
index 0000000..b1d7d22
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.JsonMapper;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class JsonMapperTest {
+
+    private static final ControllerContext controllerContext = new ControllerContext();
+
+    @BeforeClass
+    public static void init() throws FileNotFoundException {
+        Set<Module> allModules = TestUtils.loadModules(JsonMapperTest.class.getResource("/full-versions/yangs").getPath());
+        assertEquals(4, allModules.size());
+        SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+        controllerContext.setSchemas(schemaContext);
+    }
+
+    @Test
+    public void test() throws FileNotFoundException {
+        InputStream xmlStream = JsonMapperTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
+        CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream);
+        DataSchemaNode loadedSchemaNode = controllerContext.toInstanceIdentifier("ietf-interfaces:interfaces/interface/eth0").getSchemaNode();
+        JsonMapper jsonMapper = new JsonMapper();
+        String json = jsonMapper.convert(loadedSchemaNode, loadedCompositeNode);
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfImplTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfImplTest.java
new file mode 100644 (file)
index 0000000..8263c46
--- /dev/null
@@ -0,0 +1,43 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.mockito.Mockito.*;
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.controller.sal.restconf.impl.RestconfImpl;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class RestconfImplTest {
+
+    private static final RestconfImpl restconfImpl = new RestconfImpl();
+
+    @BeforeClass
+    public static void init() throws FileNotFoundException {
+        Set<Module> allModules = TestUtils.loadModules(RestconfImplTest.class.getResource("/full-versions/yangs").getPath());
+        assertEquals(4, allModules.size());
+        SchemaContext schemaContext = TestUtils.loadSchemaContext(allModules);
+        ControllerContext controllerContext = new ControllerContext();
+        controllerContext.setSchemas(schemaContext);
+        restconfImpl.setControllerContext(controllerContext);
+    }
+
+    @Test
+    public void testExample() throws FileNotFoundException {
+        InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
+        CompositeNode loadedCompositeNode = TestUtils.loadCompositeNode(xmlStream);
+        BrokerFacade brokerFacade = mock(BrokerFacade.class);
+        when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(loadedCompositeNode);
+        assertEquals(loadedCompositeNode, brokerFacade.readOperationalData(null));
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/TestUtils.java
new file mode 100644 (file)
index 0000000..c32e350
--- /dev/null
@@ -0,0 +1,116 @@
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+final class TestUtils {
+
+    private static final Logger logger = LoggerFactory.getLogger(TestUtils.class);
+
+    private final static YangModelParser parser = new YangParserImpl();
+
+    public static Set<Module> loadModules(String resourceDirectory) throws FileNotFoundException {
+        final File testDir = new File(resourceDirectory);
+        final String[] fileList = testDir.list();
+        final List<File> testFiles = new ArrayList<File>();
+        if (fileList == null) {
+            throw new FileNotFoundException(resourceDirectory);
+        }
+        for (int i = 0; i < fileList.length; i++) {
+            String fileName = fileList[i];
+            testFiles.add(new File(testDir, fileName));
+        }
+        return parser.parseYangModels(testFiles);
+    }
+
+    public static SchemaContext loadSchemaContext(Set<Module> modules) {
+        return parser.resolveSchemaContext(modules);
+    }
+
+    public static SchemaContext loadSchemaContext(String resourceDirectory) throws FileNotFoundException {
+        return parser.resolveSchemaContext(loadModules(resourceDirectory));
+    }
+
+    public static Module findModule(Set<Module> modules, String moduleName) {
+        Module result = null;
+        for (Module module : modules) {
+            if (module.getName().equals(moduleName)) {
+                result = module;
+                break;
+            }
+        }
+        return result;
+    }
+
+    public static CompositeNode loadCompositeNode(InputStream xmlInputStream) throws FileNotFoundException {
+        if (xmlInputStream == null) {
+            throw new IllegalArgumentException();
+        }
+        Node<?> dataTree;
+        try {
+            dataTree = XmlTreeBuilder.buildDataTree(xmlInputStream);
+        } catch (XMLStreamException e) {
+            logger.error("Error during building data tree from XML", e);
+            return null;
+        }
+        if (dataTree == null) {
+            logger.error("data tree is null");
+            return null;
+        }
+        if (dataTree instanceof SimpleNode) {
+            logger.error("RPC XML was resolved as SimpleNode");
+            return null;
+        }
+        return (CompositeNode) dataTree;
+    }
+
+    public static String getDocumentInPrintableForm(Document doc) {
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            TransformerFactory tf = TransformerFactory.newInstance();
+            Transformer transformer = tf.newTransformer();
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+
+            transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(out, "UTF-8")));
+            byte[] charData = out.toByteArray();
+            return new String(charData, "UTF-8");
+        } catch (IOException | TransformerException e) {
+            String msg = "Error during transformation of Document into String";
+            logger.error(msg, e);
+            return msg;
+        }
+
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/parts/ietf-interfaces_interfaces.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/parts/ietf-interfaces_interfaces.xml
new file mode 100644 (file)
index 0000000..988ba7a
--- /dev/null
@@ -0,0 +1,6 @@
+<interface>
+  <name>eth0</name>
+  <type>ethernetCsmacd</type>
+  <enabled>false</enabled>
+  <description>some interface</description>
+</interface>