BUG 907 distinguish augmented nodes 14/9014/8
authorJozef Gloncak <jgloncak@cisco.com>
Tue, 15 Jul 2014 09:10:57 +0000 (11:10 +0200)
committerJozef Gloncak <jgloncak@cisco.com>
Mon, 11 Aug 2014 11:09:24 +0000 (13:09 +0200)
All nodes and their child contains also information about module from
which they comes from (module_name:node_name)

Change-Id: I7b146e820da1b5d3bdb62510a48e6845a78c80a2
Signed-off-by: Jozef Gloncak <jgloncak@cisco.com>
opendaylight/md-sal/sal-rest-docgen/pom.xml
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/BaseYangSwaggerGenerator.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ModelGenerator.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/mountpoints/MountPointSwagger.java
opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/util/RestDocgenUtil.java [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGeneratorTest.java
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/DocGenTestHelper.java
opendaylight/md-sal/sal-rest-docgen/src/test/java/org/opendaylight/controller/sal/rest/doc/impl/MountPointSwaggerTest.java
opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_augmented.yang [new file with mode: 0644]
opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_short.yang

index 0c8b4d5a2ada924025aa40ff805d9c4613606e66..1141e1d72e212204ed21ffcf725e4226835e427b 100644 (file)
       <artifactId>mockito-all</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-api</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
index 82409d2e4033050833c7285927e5db23d0d20fc6..633d419fa9ae4219e2d276eb530fe4780514a88d 100644 (file)
@@ -7,8 +7,8 @@
  */
 package org.opendaylight.controller.sal.rest.doc.impl;
 
+import com.google.common.base.Preconditions;
 import javax.ws.rs.core.UriInfo;
-
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
 import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
@@ -16,11 +16,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
-
 /**
- * This class gathers all yang defined {@link Module}s and generates Swagger
- * compliant documentation.
+ * This class gathers all yang defined {@link Module}s and generates Swagger compliant documentation.
  */
 public class ApiDocGenerator extends BaseYangSwaggerGenerator {
 
index 5ba8b26bc1eb6bb69ac0d5e3564dbbfe5f8c27cf..1b2718251446dde021d3cc62b794b990f8852dc4 100644 (file)
@@ -7,6 +7,12 @@
  */
 package org.opendaylight.controller.sal.rest.doc.impl;
 
+import static org.opendaylight.controller.sal.rest.doc.util.RestDocgenUtil.resolvePathArgumentsName;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
+import com.google.common.base.Preconditions;
 import java.io.IOException;
 import java.net.URI;
 import java.text.DateFormat;
@@ -22,9 +28,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
-
 import javax.ws.rs.core.UriInfo;
-
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.opendaylight.controller.sal.rest.doc.model.builder.OperationBuilder;
@@ -46,11 +50,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
-import com.google.common.base.Preconditions;
-
 public class BaseYangSwaggerGenerator {
 
     private static Logger _logger = LoggerFactory.getLogger(BaseYangSwaggerGenerator.class);
@@ -75,8 +74,7 @@ public class BaseYangSwaggerGenerator {
      * @param operType
      * @return list of modules converted to swagger compliant resource list.
      */
-    public ResourceList getResourceListing(UriInfo uriInfo, SchemaContext schemaContext,
-            String context) {
+    public ResourceList getResourceListing(UriInfo uriInfo, SchemaContext schemaContext, String context) {
 
         ResourceList resourceList = createResourceList();
 
@@ -88,11 +86,9 @@ public class BaseYangSwaggerGenerator {
 
         for (Module module : modules) {
             String revisionString = SIMPLE_DATE_FORMAT.format(module.getRevision());
-
             Resource resource = new Resource();
             _logger.debug("Working on [{},{}]...", module.getName(), revisionString);
-            ApiDeclaration doc = getApiDeclaration(module.getName(), revisionString, uriInfo,
-                    schemaContext, context);
+            ApiDeclaration doc = getApiDeclaration(module.getName(), revisionString, uriInfo, schemaContext, context);
 
             if (doc != null) {
                 resource.setPath(generatePath(uriInfo, module.getName(), revisionString));
@@ -119,8 +115,7 @@ public class BaseYangSwaggerGenerator {
         return uri.toASCIIString();
     }
 
-    public ApiDeclaration getApiDeclaration(String module, String revision, UriInfo uriInfo,
-            SchemaContext schemaContext, String context) {
+    public ApiDeclaration getApiDeclaration(String module, String revision, UriInfo uriInfo, SchemaContext schemaContext, String context) {
         Date rev = null;
         try {
             rev = SIMPLE_DATE_FORMAT.parse(revision);
@@ -128,17 +123,15 @@ public class BaseYangSwaggerGenerator {
             throw new IllegalArgumentException(e);
         }
         Module m = schemaContext.findModuleByName(module, rev);
-        Preconditions.checkArgument(m != null, "Could not find module by name,revision: " + module
-                + "," + revision);
+        Preconditions.checkArgument(m != null, "Could not find module by name,revision: " + module + "," + revision);
 
-        return getApiDeclaration(m, rev, uriInfo, schemaContext, context);
+        return getApiDeclaration(m, rev, uriInfo, context, schemaContext);
     }
 
-    public ApiDeclaration getApiDeclaration(Module module, Date revision, UriInfo uriInfo,
-            SchemaContext schemaContext, String context) {
+    public ApiDeclaration getApiDeclaration(Module module, Date revision, UriInfo uriInfo, String context, SchemaContext schemaContext) {
         String basePath = createBasePathFromUriInfo(uriInfo);
 
-        ApiDeclaration doc = getSwaggerDocSpec(module, basePath, context);
+        ApiDeclaration doc = getSwaggerDocSpec(module, basePath, context, schemaContext);
         if (doc != null) {
             return doc;
         }
@@ -152,12 +145,12 @@ public class BaseYangSwaggerGenerator {
             portPart = ":" + port;
         }
         String basePath = new StringBuilder(uriInfo.getBaseUri().getScheme()).append("://")
-                .append(uriInfo.getBaseUri().getHost()).append(portPart).append("/")
-                .append(RESTCONF_CONTEXT_ROOT).toString();
+                .append(uriInfo.getBaseUri().getHost()).append(portPart).append("/").append(RESTCONF_CONTEXT_ROOT)
+                .toString();
         return basePath;
     }
 
-    public ApiDeclaration getSwaggerDocSpec(Module m, String basePath, String context) {
+    public ApiDeclaration getSwaggerDocSpec(Module m, String basePath, String context, SchemaContext schemaContext) {
         ApiDeclaration doc = createApiDeclaration(basePath);
 
         List<Api> apis = new ArrayList<Api>();
@@ -167,22 +160,21 @@ public class BaseYangSwaggerGenerator {
         for (DataSchemaNode node : dataSchemaNodes) {
             if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) {
 
-                _logger.debug("Is Configuration node [{}] [{}]", node.isConfiguration(), node
-                        .getQName().getLocalName());
+                _logger.debug("Is Configuration node [{}] [{}]", node.isConfiguration(), node.getQName().getLocalName());
 
                 List<Parameter> pathParams = new ArrayList<Parameter>();
-                String resourcePath = getDataStorePath("/config/", context) + m.getName() + ":";
-                addApis(node, apis, resourcePath, pathParams, true);
+                String resourcePath = getDataStorePath("/config/", context);
+                addApis(node, apis, resourcePath, pathParams, schemaContext, true);
 
                 pathParams = new ArrayList<Parameter>();
-                resourcePath = getDataStorePath("/operational/", context) + m.getName() + ":";
-                addApis(node, apis, resourcePath, pathParams, false);
+                resourcePath = getDataStorePath("/operational/", context);
+                addApis(node, apis, resourcePath, pathParams, schemaContext, false);
             }
 
             Set<RpcDefinition> rpcs = m.getRpcs();
             for (RpcDefinition rpcDefinition : rpcs) {
-                String resourcePath = getDataStorePath("/operations/", context) + m.getName() + ":";
-                addRpcs(rpcDefinition, apis, resourcePath);
+                String resourcePath = getDataStorePath("/operations/", context);
+                addRpcs(rpcDefinition, apis, resourcePath, schemaContext);
             }
         }
 
@@ -193,7 +185,7 @@ public class BaseYangSwaggerGenerator {
             JSONObject models = null;
 
             try {
-                models = jsonConverter.convertToJsonSchema(m);
+                models = jsonConverter.convertToJsonSchema(m, schemaContext);
                 doc.setModels(models);
                 if (_logger.isDebugEnabled()) {
                     _logger.debug(mapper.writeValueAsString(doc));
@@ -228,13 +220,13 @@ public class BaseYangSwaggerGenerator {
         return module + "(" + revision + ")";
     }
 
-    private void addApis(DataSchemaNode node, List<Api> apis, String parentPath,
-            List<Parameter> parentPathParams, boolean addConfigApi) {
+    private void addApis(DataSchemaNode node, List<Api> apis, String parentPath, List<Parameter> parentPathParams, SchemaContext schemaContext,
+            boolean addConfigApi) {
 
         Api api = new Api();
         List<Parameter> pathParams = new ArrayList<Parameter>(parentPathParams);
 
-        String resourcePath = parentPath + createPath(node, pathParams) + "/";
+        String resourcePath = parentPath + createPath(node, pathParams, schemaContext) + "/";
         _logger.debug("Adding path: [{}]", resourcePath);
         api.setPath(resourcePath);
         api.setOperations(operations(node, pathParams, addConfigApi));
@@ -248,7 +240,7 @@ public class BaseYangSwaggerGenerator {
                 if (childNode instanceof ListSchemaNode || childNode instanceof ContainerSchemaNode) {
                     // keep config and operation attributes separate.
                     if (childNode.isConfiguration() == addConfigApi) {
-                        addApis(childNode, apis, resourcePath, pathParams, addConfigApi);
+                        addApis(childNode, apis, resourcePath, pathParams, schemaContext, addConfigApi);
                     }
                 }
             }
@@ -261,8 +253,7 @@ public class BaseYangSwaggerGenerator {
      * @param pathParams
      * @return
      */
-    private List<Operation> operations(DataSchemaNode node, List<Parameter> pathParams,
-            boolean isConfig) {
+    private List<Operation> operations(DataSchemaNode node, List<Parameter> pathParams, boolean isConfig) {
         List<Operation> operations = new ArrayList<>();
 
         OperationBuilder.Get getBuilder = new OperationBuilder.Get(node, isConfig);
@@ -281,41 +272,37 @@ public class BaseYangSwaggerGenerator {
         return operations;
     }
 
-    private String createPath(final DataSchemaNode schemaNode, List<Parameter> pathParams) {
+    private String createPath(final DataSchemaNode schemaNode, List<Parameter> pathParams, SchemaContext schemaContext) {
         ArrayList<LeafSchemaNode> pathListParams = new ArrayList<LeafSchemaNode>();
         StringBuilder path = new StringBuilder();
-        QName _qName = schemaNode.getQName();
-        String localName = _qName.getLocalName();
+        String localName = resolvePathArgumentsName(schemaNode, schemaContext);
         path.append(localName);
 
         if ((schemaNode instanceof ListSchemaNode)) {
             final List<QName> listKeys = ((ListSchemaNode) schemaNode).getKeyDefinition();
             for (final QName listKey : listKeys) {
-                {
-                    DataSchemaNode _dataChildByName = ((DataNodeContainer) schemaNode)
-                            .getDataChildByName(listKey);
-                    pathListParams.add(((LeafSchemaNode) _dataChildByName));
-
-                    String pathParamIdentifier = new StringBuilder("/{")
-                            .append(listKey.getLocalName()).append("}").toString();
-                    path.append(pathParamIdentifier);
-
-                    Parameter pathParam = new Parameter();
-                    pathParam.setName(listKey.getLocalName());
-                    pathParam.setDescription(_dataChildByName.getDescription());
-                    pathParam.setType("string");
-                    pathParam.setParamType("path");
-
-                    pathParams.add(pathParam);
-                }
+                DataSchemaNode _dataChildByName = ((DataNodeContainer) schemaNode).getDataChildByName(listKey);
+                pathListParams.add(((LeafSchemaNode) _dataChildByName));
+
+                String pathParamIdentifier = new StringBuilder("/{").append(listKey.getLocalName()).append("}")
+                        .toString();
+                path.append(pathParamIdentifier);
+
+                Parameter pathParam = new Parameter();
+                pathParam.setName(listKey.getLocalName());
+                pathParam.setDescription(_dataChildByName.getDescription());
+                pathParam.setType("string");
+                pathParam.setParamType("path");
+
+                pathParams.add(pathParam);
             }
         }
         return path.toString();
     }
 
-    protected void addRpcs(RpcDefinition rpcDefn, List<Api> apis, String parentPath) {
+    protected void addRpcs(RpcDefinition rpcDefn, List<Api> apis, String parentPath, SchemaContext schemaContext) {
         Api rpc = new Api();
-        String resourcePath = parentPath + rpcDefn.getQName().getLocalName();
+        String resourcePath = parentPath + resolvePathArgumentsName(rpcDefn, schemaContext);
         rpc.setPath(resourcePath);
 
         Operation operationSpec = new Operation();
@@ -364,4 +351,5 @@ public class BaseYangSwaggerGenerator {
         }
         return sortedModules;
     }
+
 }
index 95bb1a094371db4f17d38c310c0043b07006c5c3..819892f6477b2994e53c927cf1ab3a8dd2c2b545 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.sal.rest.doc.impl;
 
+import static org.opendaylight.controller.sal.rest.doc.util.RestDocgenUtil.resolveNodesName;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -19,6 +21,7 @@ import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.opendaylight.controller.sal.rest.doc.model.builder.OperationBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
@@ -31,6 +34,7 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
@@ -86,8 +90,8 @@ public class ModelGenerator {
     private static final String NUMBER = "number";
     private static final String BOOLEAN = "boolean";
     private static final String STRING = "string";
-  private static final String ID_KEY = "id";
-  private static final String SUB_TYPES_KEY = "subTypes";
+    private static final String ID_KEY = "id";
+    private static final String SUB_TYPES_KEY = "subTypes";
 
     private static final Map<Class<? extends TypeDefinition<?>>, String> YANG_TYPE_TO_JSON_TYPE_MAPPING;
 
@@ -111,18 +115,21 @@ public class ModelGenerator {
         YANG_TYPE_TO_JSON_TYPE_MAPPING = Collections.unmodifiableMap(tempMap1);
     }
 
+    private Module topLevelModule;
+
     public ModelGenerator() {
     }
 
-    public JSONObject convertToJsonSchema(Module module) throws IOException, JSONException {
+    public JSONObject convertToJsonSchema(Module module, SchemaContext schemaContext) throws IOException, JSONException {
         JSONObject models = new JSONObject();
-        processContainers(module, models);
-        processRPCs(module, models);
-    processIdentities(module, models);
+        topLevelModule = module;
+        processContainers(module, models, schemaContext);
+        processRPCs(module, models, schemaContext);
+        processIdentities(module, models);
         return models;
     }
 
-    private void processContainers(Module module, JSONObject models) throws IOException,
+    private void processContainers(Module module, JSONObject models, SchemaContext schemaContext) throws IOException,
             JSONException {
 
         String moduleName = module.getName();
@@ -136,10 +143,10 @@ public class ModelGenerator {
              * For every container in the module
              */
             if (childNode instanceof ContainerSchemaNode) {
-                configModuleJSON = processContainer((ContainerSchemaNode) childNode, moduleName,
-                        true, models, true);
-                operationalModuleJSON = processContainer((ContainerSchemaNode) childNode,
-                        moduleName, true, models, false);
+                configModuleJSON = processContainer((ContainerSchemaNode) childNode, moduleName, true, models, true,
+                        schemaContext);
+                operationalModuleJSON = processContainer((ContainerSchemaNode) childNode, moduleName, true, models,
+                        false, schemaContext);
             }
 
             if (configModuleJSON != null) {
@@ -157,15 +164,15 @@ public class ModelGenerator {
     }
 
     /**
-     * Process the RPCs for a Module Spits out a file each of the name
-     * <rpcName>-input.json and <rpcName>-output.json for each RPC that contains
-     * input & output elements
+     * Process the RPCs for a Module Spits out a file each of the name <rpcName>-input.json and <rpcName>-output.json
+     * for each RPC that contains input & output elements
      *
      * @param module
      * @throws JSONException
      * @throws IOException
      */
-    private void processRPCs(Module module, JSONObject models) throws JSONException, IOException {
+    private void processRPCs(Module module, JSONObject models, SchemaContext schemaContext) throws JSONException,
+            IOException {
 
         Set<RpcDefinition> rpcs = module.getRpcs();
         String moduleName = module.getName();
@@ -173,7 +180,7 @@ public class ModelGenerator {
 
             ContainerSchemaNode input = rpc.getInput();
             if (input != null) {
-                JSONObject inputJSON = processContainer(input, moduleName, true, models);
+                JSONObject inputJSON = processContainer(input, moduleName, true, models, schemaContext);
                 String filename = "(" + rpc.getQName().getLocalName() + ")input";
                 inputJSON.put("id", filename);
                 // writeToFile(filename, inputJSON.toString(2), moduleName);
@@ -182,7 +189,7 @@ public class ModelGenerator {
 
             ContainerSchemaNode output = rpc.getOutput();
             if (output != null) {
-                JSONObject outputJSON = processContainer(output, moduleName, true, models);
+                JSONObject outputJSON = processContainer(output, moduleName, true, models, schemaContext);
                 String filename = "(" + rpc.getQName().getLocalName() + ")output";
                 outputJSON.put("id", filename);
                 models.put(filename, outputJSON);
@@ -190,58 +197,59 @@ public class ModelGenerator {
         }
     }
 
-  /**
-   * Processes the 'identity' statement in a yang model
-   * and maps it to a 'model' in the Swagger JSON spec.
-   *
-   * @param module The module from which the identity stmt will be processed
-   * @param models The JSONObject in which the parsed identity will be put as a 'model' obj
-   * @throws JSONException
-   */
-  private void processIdentities(Module module, JSONObject models) throws JSONException {
-
-    String moduleName = module.getName();
-    Set<IdentitySchemaNode> idNodes =  module.getIdentities();
-    _logger.debug("Processing Identities for module {} . Found {} identity statements", moduleName, idNodes.size());
-
-    for(IdentitySchemaNode idNode : idNodes){
-      JSONObject identityObj=new JSONObject();
-      String identityName = idNode.getQName().getLocalName();
-      _logger.debug("Processing Identity: {}", identityName);
-
-      identityObj.put(ID_KEY, identityName);
-      identityObj.put(DESCRIPTION_KEY, idNode.getDescription());
-
-      JSONObject props = new JSONObject();
-      IdentitySchemaNode baseId = idNode.getBaseIdentity();
+    /**
+     * Processes the 'identity' statement in a yang model and maps it to a 'model' in the Swagger JSON spec.
+     *
+     * @param module
+     *            The module from which the identity stmt will be processed
+     * @param models
+     *            The JSONObject in which the parsed identity will be put as a 'model' obj
+     * @throws JSONException
+     */
+    private void processIdentities(Module module, JSONObject models) throws JSONException {
 
+        String moduleName = module.getName();
+        Set<IdentitySchemaNode> idNodes = module.getIdentities();
+        _logger.debug("Processing Identities for module {} . Found {} identity statements", moduleName, idNodes.size());
+
+        for (IdentitySchemaNode idNode : idNodes) {
+            JSONObject identityObj = new JSONObject();
+            String identityName = idNode.getQName().getLocalName();
+            _logger.debug("Processing Identity: {}", identityName);
+
+            identityObj.put(ID_KEY, identityName);
+            identityObj.put(DESCRIPTION_KEY, idNode.getDescription());
+
+            JSONObject props = new JSONObject();
+            IdentitySchemaNode baseId = idNode.getBaseIdentity();
+
+            if (baseId == null) {
+                /**
+                 * This is a base identity. So lets see if it has sub types. If it does, then add them to the model
+                 * definition.
+                 */
+                Set<IdentitySchemaNode> derivedIds = idNode.getDerivedIdentities();
+
+                if (derivedIds != null) {
+                    JSONArray subTypes = new JSONArray();
+                    for (IdentitySchemaNode derivedId : derivedIds) {
+                        subTypes.put(derivedId.getQName().getLocalName());
+                    }
+                    identityObj.put(SUB_TYPES_KEY, subTypes);
+                }
+            } else {
+                /**
+                 * This is a derived entity. Add it's base type & move on.
+                 */
+                props.put(TYPE_KEY, baseId.getQName().getLocalName());
+            }
 
-      if(baseId==null) {
-        /**
-         * This is a base identity. So lets see if
-         * it has sub types. If it does, then add them to the model definition.
-         */
-        Set<IdentitySchemaNode> derivedIds = idNode.getDerivedIdentities();
-
-        if(derivedIds != null) {
-          JSONArray subTypes = new JSONArray();
-          for(IdentitySchemaNode derivedId : derivedIds){
-            subTypes.put(derivedId.getQName().getLocalName());
-          }
-          identityObj.put(SUB_TYPES_KEY, subTypes);
+            // Add the properties. For a base type, this will be an empty object as required by the Swagger spec.
+            identityObj.put(PROPERTIES_KEY, props);
+            models.put(identityName, identityObj);
         }
-      } else {
-        /**
-         * This is a derived entity. Add it's base type & move on.
-         */
-        props.put(TYPE_KEY, baseId.getQName().getLocalName());
-      }
-
-      //Add the properties. For a base type, this will be an empty object as required by the Swagger spec.
-      identityObj.put(PROPERTIES_KEY, props);
-      models.put(identityName, identityObj);
     }
-  }
+
     /**
      * Processes the container node and populates the moduleJSON
      *
@@ -251,14 +259,13 @@ public class ModelGenerator {
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processContainer(ContainerSchemaNode container, String moduleName,
-            boolean addSchemaStmt, JSONObject models) throws JSONException, IOException {
-        return processContainer(container, moduleName, addSchemaStmt, models, (Boolean) null);
+    private JSONObject processContainer(ContainerSchemaNode container, String moduleName, boolean addSchemaStmt,
+            JSONObject models, SchemaContext schemaContext) throws JSONException, IOException {
+        return processContainer(container, moduleName, addSchemaStmt, models, (Boolean) null, schemaContext);
     }
 
-    private JSONObject processContainer(ContainerSchemaNode container, String moduleName,
-            boolean addSchemaStmt, JSONObject models, Boolean isConfig) throws JSONException,
-            IOException {
+    private JSONObject processContainer(ContainerSchemaNode container, String moduleName, boolean addSchemaStmt,
+            JSONObject models, Boolean isConfig, SchemaContext schemaContext) throws JSONException, IOException {
         JSONObject moduleJSON = getSchemaTemplate();
         if (addSchemaStmt) {
             moduleJSON = getSchemaTemplate();
@@ -270,57 +277,58 @@ public class ModelGenerator {
         String containerDescription = container.getDescription();
         moduleJSON.put(DESCRIPTION_KEY, containerDescription);
 
-        JSONObject properties = processChildren(container.getChildNodes(), moduleName, models, isConfig);
+        JSONObject properties = processChildren(container.getChildNodes(), container.getQName(), moduleName, models,
+                isConfig, schemaContext);
         moduleJSON.put(PROPERTIES_KEY, properties);
         return moduleJSON;
     }
 
-    private JSONObject processChildren(Iterable<DataSchemaNode> nodes, String moduleName,
-            JSONObject models) throws JSONException, IOException {
-        return processChildren(nodes, moduleName, models, null);
+    private JSONObject processChildren(Iterable<DataSchemaNode> nodes, QName parentQName, String moduleName,
+            JSONObject models, SchemaContext schemaContext) throws JSONException, IOException {
+        return processChildren(nodes, parentQName, moduleName, models, null, schemaContext);
     }
 
     /**
      * Processes the nodes
      *
      * @param nodes
+     * @param parentQName
      * @param moduleName
      * @param isConfig
      * @return
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processChildren(Iterable<DataSchemaNode> nodes, String moduleName,
-            JSONObject models, Boolean isConfig) throws JSONException, IOException {
+    private JSONObject processChildren(Iterable<DataSchemaNode> nodes, QName parentQName, String moduleName,
+            JSONObject models, Boolean isConfig, SchemaContext schemaContext) throws JSONException, IOException {
 
         JSONObject properties = new JSONObject();
 
         for (DataSchemaNode node : nodes) {
             if (isConfig == null || node.isConfiguration() == isConfig) {
 
-                String name = node.getQName().getLocalName();
+                String name = resolveNodesName(node, topLevelModule, schemaContext);
                 JSONObject property = null;
                 if (node instanceof LeafSchemaNode) {
                     property = processLeafNode((LeafSchemaNode) node);
                 } else if (node instanceof ListSchemaNode) {
-                    property = processListSchemaNode((ListSchemaNode) node, moduleName, models, isConfig);
+                    property = processListSchemaNode((ListSchemaNode) node, moduleName, models, isConfig, schemaContext);
 
                 } else if (node instanceof LeafListSchemaNode) {
                     property = processLeafListNode((LeafListSchemaNode) node);
 
                 } else if (node instanceof ChoiceNode) {
-                    property = processChoiceNode((ChoiceNode) node, moduleName, models);
+                    property = processChoiceNode((ChoiceNode) node, moduleName, models, schemaContext);
 
                 } else if (node instanceof AnyXmlSchemaNode) {
                     property = processAnyXMLNode((AnyXmlSchemaNode) node);
 
                 } else if (node instanceof ContainerSchemaNode) {
-                    property = processContainer((ContainerSchemaNode) node, moduleName, false,
-                            models, isConfig);
+                    property = processContainer((ContainerSchemaNode) node, moduleName, false, models, isConfig,
+                            schemaContext);
 
                 } else {
-                    throw new IllegalArgumentException("Unknown DataSchemaNode type: "
-                            + node.getClass());
+                    throw new IllegalArgumentException("Unknown DataSchemaNode type: " + node.getClass());
                 }
 
                 property.putOpt(DESCRIPTION_KEY, node.getDescription());
@@ -356,15 +364,16 @@ public class ModelGenerator {
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processChoiceNode(ChoiceNode choiceNode, String moduleName, JSONObject models)
-            throws JSONException, IOException {
+    private JSONObject processChoiceNode(ChoiceNode choiceNode, String moduleName, JSONObject models,
+            SchemaContext schemaContext) throws JSONException, IOException {
 
         Set<ChoiceCaseNode> cases = choiceNode.getCases();
 
         JSONArray choiceProps = new JSONArray();
         for (ChoiceCaseNode choiceCase : cases) {
             String choiceName = choiceCase.getQName().getLocalName();
-            JSONObject choiceProp = processChildren(choiceCase.getChildNodes(), moduleName, models);
+            JSONObject choiceProp = processChildren(choiceCase.getChildNodes(), choiceCase.getQName(), moduleName,
+                    models, schemaContext);
             JSONObject choiceObj = new JSONObject();
             choiceObj.put(choiceName, choiceProp);
             choiceObj.put(TYPE_KEY, OBJECT_TYPE);
@@ -384,8 +393,7 @@ public class ModelGenerator {
      * @param props
      * @throws JSONException
      */
-    private void processConstraints(ConstraintDefinition constraints, JSONObject props)
-            throws JSONException {
+    private void processConstraints(ConstraintDefinition constraints, JSONObject props) throws JSONException {
         boolean isMandatory = constraints.isMandatory();
         props.put(REQUIRED_KEY, isMandatory);
 
@@ -402,9 +410,8 @@ public class ModelGenerator {
     /**
      * Parses a ListSchema node.
      *
-     * Due to a limitation of the RAML--->JAX-RS tool, sub-properties must be in
-     * a separate JSON schema file. Hence, we have to write some properties to a
-     * new file, while continuing to process the rest.
+     * Due to a limitation of the RAML--->JAX-RS tool, sub-properties must be in a separate JSON schema file. Hence, we
+     * have to write some properties to a new file, while continuing to process the rest.
      *
      * @param listNode
      * @param moduleName
@@ -413,21 +420,21 @@ public class ModelGenerator {
      * @throws JSONException
      * @throws IOException
      */
-    private JSONObject processListSchemaNode(ListSchemaNode listNode, String moduleName,
-            JSONObject models, Boolean isConfig) throws JSONException, IOException {
+    private JSONObject processListSchemaNode(ListSchemaNode listNode, String moduleName, JSONObject models,
+            Boolean isConfig, SchemaContext schemaContext) throws JSONException, IOException {
 
-        String fileName = (BooleanUtils.isNotFalse(isConfig)?OperationBuilder.CONFIG:OperationBuilder.OPERATIONAL) +
-                                                                listNode.getQName().getLocalName();
+        String fileName = (BooleanUtils.isNotFalse(isConfig) ? OperationBuilder.CONFIG : OperationBuilder.OPERATIONAL)
+                + listNode.getQName().getLocalName();
 
-        JSONObject childSchemaProperties = processChildren(listNode.getChildNodes(), moduleName, models);
+        JSONObject childSchemaProperties = processChildren(listNode.getChildNodes(), listNode.getQName(), moduleName,
+                models, schemaContext);
         JSONObject childSchema = getSchemaTemplate();
         childSchema.put(TYPE_KEY, OBJECT_TYPE);
         childSchema.put(PROPERTIES_KEY, childSchemaProperties);
 
         /*
-         * Due to a limitation of the RAML--->JAX-RS tool, sub-properties must
-         * be in a separate JSON schema file. Hence, we have to write some
-         * properties to a new file, while continuing to process the rest.
+         * Due to a limitation of the RAML--->JAX-RS tool, sub-properties must be in a separate JSON schema file. Hence,
+         * we have to write some properties to a new file, while continuing to process the rest.
          */
         // writeToFile(fileName, childSchema.toString(2), moduleName);
         childSchema.put("id", fileName);
@@ -483,8 +490,7 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processTypeDef(TypeDefinition<?> leafTypeDef, JSONObject property)
-            throws JSONException {
+    private void processTypeDef(TypeDefinition<?> leafTypeDef, JSONObject property) throws JSONException {
 
         if (leafTypeDef instanceof ExtendedType) {
             processExtendedType(leafTypeDef, property);
@@ -498,7 +504,7 @@ public class ModelGenerator {
             processUnionType((UnionTypeDefinition) leafTypeDef, property);
 
         } else if (leafTypeDef instanceof IdentityrefTypeDefinition) {
-      property.putOpt(TYPE_KEY, ((IdentityrefTypeDefinition) leafTypeDef).getIdentity().getQName().getLocalName());
+            property.putOpt(TYPE_KEY, ((IdentityrefTypeDefinition) leafTypeDef).getIdentity().getQName().getLocalName());
         } else if (leafTypeDef instanceof BinaryTypeDefinition) {
             processBinaryType((BinaryTypeDefinition) leafTypeDef, property);
         } else {
@@ -517,15 +523,13 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processExtendedType(TypeDefinition<?> leafTypeDef, JSONObject property)
-            throws JSONException {
+    private void processExtendedType(TypeDefinition<?> leafTypeDef, JSONObject property) throws JSONException {
         Object leafBaseType = leafTypeDef.getBaseType();
         if (leafBaseType instanceof ExtendedType) {
             // recursively process an extended type until we hit a base type
             processExtendedType((TypeDefinition<?>) leafBaseType, property);
         } else {
-            List<LengthConstraint> lengthConstraints = ((ExtendedType) leafTypeDef)
-                    .getLengthConstraints();
+            List<LengthConstraint> lengthConstraints = ((ExtendedType) leafTypeDef).getLengthConstraints();
             for (LengthConstraint lengthConstraint : lengthConstraints) {
                 Number min = lengthConstraint.getMin();
                 Number max = lengthConstraint.getMax();
@@ -541,8 +545,7 @@ public class ModelGenerator {
     /*
    *
    */
-    private void processBinaryType(BinaryTypeDefinition binaryType, JSONObject property)
-            throws JSONException {
+    private void processBinaryType(BinaryTypeDefinition binaryType, JSONObject property) throws JSONException {
         property.put(TYPE_KEY, STRING);
         JSONObject media = new JSONObject();
         media.put(BINARY_ENCODING_KEY, BASE_64);
@@ -555,8 +558,7 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processEnumType(EnumerationType enumLeafType, JSONObject property)
-            throws JSONException {
+    private void processEnumType(EnumerationType enumLeafType, JSONObject property) throws JSONException {
         List<EnumPair> enumPairs = enumLeafType.getValues();
         List<String> enumNames = new ArrayList<String>();
         for (EnumPair enumPair : enumPairs) {
@@ -571,8 +573,7 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processBitsType(BitsTypeDefinition bitsType, JSONObject property)
-            throws JSONException {
+    private void processBitsType(BitsTypeDefinition bitsType, JSONObject property) throws JSONException {
         property.put(TYPE_KEY, ARRAY_TYPE);
         property.put(MIN_ITEMS, 0);
         property.put(UNIQUE_ITEMS_KEY, true);
@@ -593,18 +594,17 @@ public class ModelGenerator {
      * @param property
      * @throws JSONException
      */
-    private void processUnionType(UnionTypeDefinition unionType, JSONObject property)
-            throws JSONException {
+    private void processUnionType(UnionTypeDefinition unionType, JSONObject property) throws JSONException {
 
         StringBuilder type = new StringBuilder();
-        for (TypeDefinition<?> typeDef : unionType.getTypes() ) {
-            if( type.length() > 0 ){
-                type.append( " or " );
+        for (TypeDefinition<?> typeDef : unionType.getTypes()) {
+            if (type.length() > 0) {
+                type.append(" or ");
             }
             type.append(YANG_TYPE_TO_JSON_TYPE_MAPPING.get(typeDef.getClass()));
         }
 
-        property.put(TYPE_KEY, type );
+        property.put(TYPE_KEY, type);
     }
 
     /**
@@ -619,4 +619,5 @@ public class ModelGenerator {
 
         return schemaJSON;
     }
+
 }
index 29ada12c6f8737a3d61fc5e68abde7cece17fad1..7e8707110fb757e9fae69fb2e02837d34d5b22cf 100644 (file)
@@ -17,9 +17,7 @@ import java.util.Map.Entry;
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
-
 import javax.ws.rs.core.UriInfo;
-
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/util/RestDocgenUtil.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/util/RestDocgenUtil.java
new file mode 100644 (file)
index 0000000..9e1d82a
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.rest.doc.util;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+public class RestDocgenUtil {
+
+    private RestDocgenUtil() {
+    }
+
+    private static Map<URI, Map<Date, Module>> namespaceAndRevisionToModule = new HashMap<URI, Map<Date, Module>>();
+
+    /**
+     * Resolve path argument name for {@code node}.
+     *
+     * The name can contain also prefix which consists of module name followed by colon. The module prefix is presented
+     * if namespace of {@code node} and its parent is different. In other cases only name of {@code node} is returned.
+     *
+     * @return name of {@code node}
+     */
+    public static String resolvePathArgumentsName(final SchemaNode node, final SchemaContext schemaContext) {
+        Iterable<QName> schemaPath = node.getPath().getPathTowardsRoot();
+        Iterator<QName> it = schemaPath.iterator();
+        QName nodeQName = it.next();
+
+        QName parentQName = null;
+        if (it.hasNext()) {
+            parentQName = it.next();
+        }
+        if (isEqualNamespaceAndRevision(parentQName, nodeQName)) {
+            return node.getQName().getLocalName();
+        } else {
+            return resolveFullNameFromNode(node, schemaContext);
+        }
+    }
+
+    private synchronized static String resolveFullNameFromNode(final SchemaNode node, final SchemaContext schemaContext) {
+        final URI namespace = node.getQName().getNamespace();
+        final Date revision = node.getQName().getRevision();
+
+        Map<Date, Module> revisionToModule = namespaceAndRevisionToModule.get(namespace);
+        if (revisionToModule == null) {
+            revisionToModule = new HashMap<>();
+            namespaceAndRevisionToModule.put(namespace, revisionToModule);
+        }
+        Module module = revisionToModule.get(revision);
+        if (module == null) {
+            module = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+            revisionToModule.put(revision, module);
+        }
+        if (module != null) {
+            return module.getName() + ":" + node.getQName().getLocalName();
+        }
+        return node.getQName().getLocalName();
+    }
+
+    public static String resolveNodesName(final SchemaNode node, final Module module, final SchemaContext schemaContext) {
+        if (node.getQName().getNamespace().equals(module.getQNameModule().getNamespace())
+                && node.getQName().getRevision().equals(module.getQNameModule().getRevision())) {
+            return node.getQName().getLocalName();
+        } else {
+            return resolveFullNameFromNode(node, schemaContext);
+        }
+    }
+
+    private static boolean isEqualNamespaceAndRevision(QName parentQName, QName nodeQName) {
+        if (parentQName == null) {
+            if (nodeQName == null) {
+                return true;
+            }
+            return false;
+        }
+        return parentQName.getNamespace().equals(nodeQName.getNamespace())
+                && parentQName.getRevision().equals(nodeQName.getRevision());
+    }
+}
index 07c9378439d2f66551672d8a08ec20785a0a074b..19f82b53867b603af20576759485999ca1fe28c4 100644 (file)
@@ -5,16 +5,17 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import com.google.common.base.Preconditions;
 import java.io.File;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeSet;
-
 import javax.ws.rs.core.UriInfo;
-
 import junit.framework.Assert;
-
+import org.json.JSONException;
+import org.json.JSONObject;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -25,8 +26,8 @@ import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
 import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
 import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
 import org.opendaylight.yangtools.yang.model.api.Module;
-
-import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
 /**
  *
@@ -36,12 +37,14 @@ public class ApiDocGeneratorTest {
     public static final String HTTP_HOST = "http://host";
     private ApiDocGenerator generator;
     private DocGenTestHelper helper;
+    private SchemaContext schemaContext;
 
     @Before
     public void setUp() throws Exception {
         generator = new ApiDocGenerator();
         helper = new DocGenTestHelper();
         helper.setUp();
+        schemaContext = new YangParserImpl().resolveSchemaContext(new HashSet<Module>(helper.getModules().values()));
     }
 
     @After
@@ -59,8 +62,9 @@ public class ApiDocGeneratorTest {
         for (Entry<File, Module> m : helper.getModules().entrySet()) {
             if (m.getKey().getAbsolutePath().endsWith("toaster_short.yang")) {
                 ApiDeclaration doc = generator.getSwaggerDocSpec(m.getValue(),
-                        "http://localhost:8080/restconf", "");
+                        "http://localhost:8080/restconf", "",schemaContext);
                 validateToaster(doc);
+                validateTosterDocContainsModulePrefixes(doc);
                 Assert.assertNotNull(doc);
             }
         }
@@ -73,7 +77,7 @@ public class ApiDocGeneratorTest {
         for (Entry<File, Module> m : helper.getModules().entrySet()) {
             if (m.getKey().getAbsolutePath().endsWith("toaster.yang")) {
                 ApiDeclaration doc = generator.getSwaggerDocSpec(m.getValue(),
-                        "http://localhost:8080/restconf", "");
+                        "http://localhost:8080/restconf", "",schemaContext);
                 Assert.assertNotNull(doc);
 
                 //testing bugs.opendaylight.org bug 1290. UnionType model type.
@@ -84,11 +88,21 @@ public class ApiDocGeneratorTest {
         }
     }
 
+    /**
+     * Tests whether from yang files are generated all required paths for HTTP operations (GET, DELETE, PUT, POST)
+     *
+     * If container | list is augmented then in path there should be specified module name followed with collon (e. g.
+     * "/config/module1:element1/element2/module2:element3")
+     *
+     * @param doc
+     * @throws Exception
+     */
     private void validateToaster(ApiDeclaration doc) throws Exception {
         Set<String> expectedUrls = new TreeSet<>(Arrays.asList(new String[] {
                 "/config/toaster2:toaster/", "/operational/toaster2:toaster/",
                 "/operations/toaster2:cancel-toast", "/operations/toaster2:make-toast",
-                "/operations/toaster2:restock-toaster" }));
+                "/operations/toaster2:restock-toaster",
+                "/config/toaster2:toaster/toasterSlot/{slotId}/toaster-augmented:slotInfo/" }));
 
         Set<String> actualUrls = new TreeSet<>();
 
@@ -130,7 +144,7 @@ public class ApiDocGeneratorTest {
     @Test
     public void testGetResourceListing() throws Exception {
         UriInfo info = helper.createMockUriInfo(HTTP_HOST);
-        SchemaService mockSchemaService = helper.createMockSchemaService();
+        SchemaService mockSchemaService = helper.createMockSchemaService(schemaContext);
 
         generator.setSchemaService(mockSchemaService);
 
@@ -154,4 +168,30 @@ public class ApiDocGeneratorTest {
         assertEquals(HTTP_HOST + "/toaster2(2009-11-20)", toaster2.getPath());
     }
 
+    private void validateTosterDocContainsModulePrefixes(ApiDeclaration doc) {
+        JSONObject topLevelJson = doc.getModels();
+        try {
+            JSONObject configToaster = topLevelJson.getJSONObject("(config)toaster");
+            assertNotNull("(config)toaster JSON object missing", configToaster);
+            //without module prefix
+            containsProperties(configToaster, "toasterSlot");
+
+            JSONObject toasterSlot = topLevelJson.getJSONObject("(config)toasterSlot");
+            assertNotNull("(config)toasterSlot JSON object missing", toasterSlot);
+            //with module prefix
+            containsProperties(toasterSlot, "toaster-augmented:slotInfo");
+
+        } catch (JSONException e) {
+            fail("Json exception while reading JSON object. Original message "+e.getMessage());
+        }
+    }
+
+    private void containsProperties(final JSONObject jsonObject,final String...properties) throws JSONException {
+        for (String property : properties) {
+            JSONObject propertiesObject = jsonObject.getJSONObject("properties");
+            assertNotNull("Properties object missing in ", propertiesObject);
+            JSONObject concretePropertyObject = propertiesObject.getJSONObject(property);
+            assertNotNull(property + " is missing",concretePropertyObject);
+        }
+    }
 }
index 0f15d00e79f53ecb3815d915b55454274dff7c93..7701d2a735e1af1304139e383b556ee8f8a53492 100644 (file)
@@ -10,6 +10,9 @@ package org.opendaylight.controller.sal.rest.doc.impl;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.net.URI;
@@ -19,23 +22,17 @@ import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 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.model.parser.api.YangContextParser;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;
-
 public class DocGenTestHelper {
 
     private Map<File, Module> modules;
@@ -45,7 +42,7 @@ public class DocGenTestHelper {
             URISyntaxException {
 
         URI resourceDirUri = getClass().getResource(resourceDirectory).toURI();
-        final YangModelParser parser = new YangParserImpl();
+        final YangContextParser parser = new YangParserImpl();
         final File testDir = new File(resourceDirUri);
         final String[] fileList = testDir.list();
         final List<File> testFiles = new ArrayList<>();
@@ -90,6 +87,7 @@ public class DocGenTestHelper {
 
         final ArgumentCaptor<String> moduleCapture = ArgumentCaptor.forClass(String.class);
         final ArgumentCaptor<Date> dateCapture = ArgumentCaptor.forClass(Date.class);
+        final ArgumentCaptor<URI> namespaceCapture = ArgumentCaptor.forClass(URI.class);
         when(mockContext.findModuleByName(moduleCapture.capture(), dateCapture.capture())).then(
                 new Answer<Module>() {
                     @Override
@@ -104,6 +102,20 @@ public class DocGenTestHelper {
                         return null;
                     }
                 });
+        when(mockContext.findModuleByNamespaceAndRevision(namespaceCapture.capture(), dateCapture.capture())).then(
+                new Answer<Module>() {
+                    @Override
+                    public Module answer(InvocationOnMock invocation) throws Throwable {
+                        URI namespace = namespaceCapture.getValue();
+                        Date date = dateCapture.getValue();
+                        for (Module m : modules.values()) {
+                            if (m.getNamespace().equals(namespace) && m.getRevision().equals(date)) {
+                                return m;
+                            }
+                        }
+                        return null;
+                    }
+                });
         return mockContext;
     }
 
index bba8ed9ca6fcf557bb972af2d3c55c68bf1f3f13..940b99fd997fe919cf889c8f4902a5c748592636 100644 (file)
@@ -14,12 +14,11 @@ import static org.mockito.Mockito.when;
 
 import java.net.URISyntaxException;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
-
 import javax.ws.rs.core.UriInfo;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
@@ -33,7 +32,9 @@ import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
 import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
 public class MountPointSwaggerTest {
 
@@ -44,12 +45,14 @@ public class MountPointSwaggerTest {
     private static final String INSTANCE_URL = "nodes/node/123/";
     private MountPointSwagger swagger;
     private DocGenTestHelper helper;
+    private SchemaContext schemaContext;
 
     @Before
     public void setUp() throws Exception {
         swagger = new MountPointSwagger();
         helper = new DocGenTestHelper();
         helper.setUp();
+        schemaContext = new YangParserImpl().resolveSchemaContext(new HashSet<Module>(helper.getModules().values()));
     }
 
     @Test()
diff --git a/opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_augmented.yang b/opendaylight/md-sal/sal-rest-docgen/src/test/resources/yang/toaster_augmented.yang
new file mode 100644 (file)
index 0000000..4db7897
--- /dev/null
@@ -0,0 +1,21 @@
+module toaster-augmented {
+
+    yang-version 1;
+
+    namespace
+      "http://netconfcentral.org/ns/toaster/augmented";
+
+    prefix toast;
+    import toaster2 {prefix tst; revision-date 2009-11-20;}
+
+    revision "2014-7-14" {
+    }
+
+    augment "/tst:toaster/tst:toasterSlot" {
+        container slotInfo {
+            leaf numberOfToastPrepared {
+                type uint32;
+            }
+        }
+    }
+}
\ No newline at end of file
index a1d5ab0a129fa92d362b4faa7d1e416fd367b7ab..6884076d5daafa1a8ced3753d1460754b950e1a1 100644 (file)
                 Microsoft Toaster.";
       }
 
+      list toasterSlot {
+        key "slotId";
+        leaf slotId {
+            type string;
+        }
+      }
+
       leaf toasterModelNumber {
         type DisplayString;
         config false;