X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-docgen%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Frest%2Fdoc%2Fimpl%2FApiDocGenerator.java;h=bcd11bcb06633bd939de00a2af513353cf1b1f2d;hb=48814d6a264b8f13e5db1422336d9ef25cb05fa9;hp=3662090b87895d98a8b3d2a1dab3b0000fc6adfc;hpb=2f034183cfcbaacf2a287f1ddf00d367674868af;p=controller.git diff --git a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java index 3662090b87..bcd11bcb06 100644 --- a/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java +++ b/opendaylight/md-sal/sal-rest-docgen/src/main/java/org/opendaylight/controller/sal/rest/doc/impl/ApiDocGenerator.java @@ -7,137 +7,157 @@ */ package org.opendaylight.controller.sal.rest.doc.impl; -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; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.core.UriInfo; + import org.json.JSONException; import org.json.JSONObject; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.controller.sal.rest.doc.model.builder.OperationBuilder; -import org.opendaylight.controller.sal.rest.doc.swagger.*; +import org.opendaylight.controller.sal.rest.doc.swagger.Api; +import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration; +import org.opendaylight.controller.sal.rest.doc.swagger.Operation; +import org.opendaylight.controller.sal.rest.doc.swagger.Parameter; +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.model.api.*; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +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.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.ws.rs.core.UriInfo; -import java.io.IOException; -import java.net.URI; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; +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; /** * This class gathers all yang defined {@link Module}s and generates Swagger compliant documentation. */ public class ApiDocGenerator { - private static Logger _logger = LoggerFactory.getLogger(ApiDocGenerator.class); - - private static final ApiDocGenerator INSTANCE = new ApiDocGenerator(); - private ObjectMapper mapper = new ObjectMapper(); - private final ModelGenerator jsonConverter = new ModelGenerator(); - - private SchemaService schemaService; - - private final String API_VERSION = "1.0.0"; - private final String SWAGGER_VERSION = "1.2"; - private final String RESTCONF_CONTEXT_ROOT = "restconf"; - private final DateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - - //For now its {@link HashMap}. It will be changed to thread-safe Map when schema change listener is implemented. - private final Map MODULE_DOC_CACHE = new HashMap(); - - private ApiDocGenerator(){ - mapper.registerModule(new JsonOrgModule()); - mapper.configure(SerializationFeature.INDENT_OUTPUT, true); - } - - /** - * Returns singleton instance - * @return - */ - public static ApiDocGenerator getInstance() { - return INSTANCE; - } - - /** - * - * @param schemaService - */ - public void setSchemaService(SchemaService schemaService) { - this.schemaService = schemaService; - } - /** - * - * @param uriInfo - * @return list of modules converted to swagger compliant resource list. - */ - public ResourceList getResourceListing(UriInfo uriInfo) { - - Preconditions.checkState(schemaService != null); - SchemaContext schemaContext = schemaService.getGlobalContext(); - Preconditions.checkState(schemaContext != null); - - Set modules = schemaContext.getModules(); - - ResourceList resourceList = new ResourceList(); - resourceList.setApiVersion(API_VERSION); - resourceList.setSwaggerVersion(SWAGGER_VERSION); - - List resources = new ArrayList<>(modules.size()); - _logger.info("Modules found [{}]", modules.size()); - - for (Module module : modules) { - Resource resource = new Resource(); - String revisionString = SIMPLE_DATE_FORMAT.format(module.getRevision()); - - _logger.debug("Working on [{},{}]...", module.getName(), revisionString); - ApiDeclaration doc = getApiDeclaration(module.getName(), revisionString, uriInfo); - - if (doc != null) { - URI uri = uriInfo.getRequestUriBuilder(). - path(generateCacheKey(module.getName(), revisionString)). - build(); - - resource.setPath(uri.toASCIIString()); - resources.add(resource); - } else { - _logger.debug("Could not generate doc for {},{}", module.getName(), revisionString); - } - } + private static final Logger _logger = LoggerFactory.getLogger(ApiDocGenerator.class); - resourceList.setApis(resources); + private static final ApiDocGenerator INSTANCE = new ApiDocGenerator(); + private final ObjectMapper mapper = new ObjectMapper(); + private final ModelGenerator jsonConverter = new ModelGenerator(); - return resourceList; - } + private SchemaService schemaService; - public ApiDeclaration getApiDeclaration(String module, String revision, UriInfo uriInfo) { + private static final String API_VERSION = "1.0.0"; + private static final String SWAGGER_VERSION = "1.2"; + private static final String RESTCONF_CONTEXT_ROOT = "restconf"; + private final DateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - //Lookup cache - String cacheKey = generateCacheKey(module, revision); + //For now its {@link HashMap}. It will be changed to thread-safe Map when schema change listener is implemented. + private final Map MODULE_DOC_CACHE = new HashMap(); - if (MODULE_DOC_CACHE.containsKey(cacheKey)) { - _logger.debug("Serving from cache for {}", cacheKey); - return MODULE_DOC_CACHE.get(cacheKey); + private ApiDocGenerator(){ + mapper.registerModule(new JsonOrgModule()); + mapper.configure(SerializationFeature.INDENT_OUTPUT, true); } - Date rev = null; - try { - rev = SIMPLE_DATE_FORMAT.parse(revision); - } catch (ParseException e) { - throw new IllegalArgumentException(e); + /** + * Returns singleton instance + * @return + */ + public static ApiDocGenerator getInstance() { + return INSTANCE; } - SchemaContext schemaContext = schemaService.getGlobalContext(); - Preconditions.checkState(schemaContext != null); + /** + * + * @param schemaService + */ + public void setSchemaService(final SchemaService schemaService) { + this.schemaService = schemaService; + } + /** + * + * @param uriInfo + * @return list of modules converted to swagger compliant resource list. + */ + public ResourceList getResourceListing(final UriInfo uriInfo) { + + Preconditions.checkState(schemaService != null); + SchemaContext schemaContext = schemaService.getGlobalContext(); + Preconditions.checkState(schemaContext != null); + + Set modules = schemaContext.getModules(); + + ResourceList resourceList = new ResourceList(); + resourceList.setApiVersion(API_VERSION); + resourceList.setSwaggerVersion(SWAGGER_VERSION); + + List resources = new ArrayList<>(modules.size()); + _logger.info("Modules found [{}]", modules.size()); + + for (Module module : modules) { + Resource resource = new Resource(); + String revisionString = SIMPLE_DATE_FORMAT.format(module.getRevision()); + + _logger.debug("Working on [{},{}]...", module.getName(), revisionString); + ApiDeclaration doc = getApiDeclaration(module.getName(), revisionString, uriInfo); + + if (doc != null) { + URI uri = uriInfo.getRequestUriBuilder(). + path(generateCacheKey(module.getName(), revisionString)). + build(); + + resource.setPath(uri.toASCIIString()); + resources.add(resource); + } else { + _logger.debug("Could not generate doc for {},{}", module.getName(), revisionString); + } + } + + resourceList.setApis(resources); + + return resourceList; + } + + public ApiDeclaration getApiDeclaration(final String module, final String revision, final UriInfo uriInfo) { + + //Lookup cache + String cacheKey = generateCacheKey(module, revision); - Module m = schemaContext.findModuleByName(module, rev); - Preconditions.checkArgument(m != null, "Could not find module by name,revision: " + module + "," + revision); + if (MODULE_DOC_CACHE.containsKey(cacheKey)) { + _logger.debug("Serving from cache for {}", cacheKey); + return MODULE_DOC_CACHE.get(cacheKey); + } + + Date rev = null; + try { + rev = SIMPLE_DATE_FORMAT.parse(revision); + } catch (ParseException e) { + throw new IllegalArgumentException(e); + } - String basePath = new StringBuilder(uriInfo.getBaseUri().getScheme()) + SchemaContext schemaContext = schemaService.getGlobalContext(); + Preconditions.checkState(schemaContext != null); + + Module m = schemaContext.findModuleByName(module, rev); + Preconditions.checkArgument(m != null, "Could not find module by name,revision: " + module + "," + revision); + + String basePath = new StringBuilder(uriInfo.getBaseUri().getScheme()) .append("://") .append(uriInfo.getBaseUri().getHost()) .append(":") @@ -146,161 +166,161 @@ public class ApiDocGenerator { .append(RESTCONF_CONTEXT_ROOT) .toString(); - ApiDeclaration doc = getSwaggerDocSpec(m, basePath); - MODULE_DOC_CACHE.put(cacheKey, doc); - return doc; - } + ApiDeclaration doc = getSwaggerDocSpec(m, basePath); + MODULE_DOC_CACHE.put(cacheKey, doc); + return doc; + } - public ApiDeclaration getSwaggerDocSpec(Module m, String basePath) { - ApiDeclaration doc = new ApiDeclaration(); - doc.setApiVersion(API_VERSION); - doc.setSwaggerVersion(SWAGGER_VERSION); - doc.setBasePath(basePath); - doc.setProduces(Arrays.asList("application/json", "application/xml")); + public ApiDeclaration getSwaggerDocSpec(final Module m, final String basePath) { + ApiDeclaration doc = new ApiDeclaration(); + doc.setApiVersion(API_VERSION); + doc.setSwaggerVersion(SWAGGER_VERSION); + doc.setBasePath(basePath); + doc.setProduces(Arrays.asList("application/json", "application/xml")); - List apis = new ArrayList(); + List apis = new ArrayList(); - Set dataSchemaNodes = m.getChildNodes(); - _logger.debug("child nodes size [{}]", dataSchemaNodes.size()); - for (DataSchemaNode node : dataSchemaNodes) { - if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) { + Set dataSchemaNodes = m.getChildNodes(); + _logger.debug("child nodes size [{}]", dataSchemaNodes.size()); + 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 pathParams = null; - if (node.isConfiguration()) { - pathParams = new ArrayList(); - String resourcePath = "/config/" + m.getName() + ":"; - addApis(node, apis, resourcePath, pathParams, true); + List pathParams = null; + if (node.isConfiguration()) { + pathParams = new ArrayList(); + String resourcePath = "/config/" + m.getName() + ":"; + addApis(node, apis, resourcePath, pathParams, true); + } + + pathParams = new ArrayList(); + String resourcePath = "/operational/" + m.getName() + ":"; + addApis(node, apis, resourcePath, pathParams, false); + } } - pathParams = new ArrayList(); - String resourcePath = "/operational/" + m.getName() + ":"; - addApis(node, apis, resourcePath, pathParams, false); - } - } + Set rpcs = m.getRpcs(); + for (RpcDefinition rpcDefinition : rpcs) { + String resourcePath = "/operations/" + m.getName() + ":"; + addRpcs(rpcDefinition, apis, resourcePath); - Set rpcs = m.getRpcs(); - for (RpcDefinition rpcDefinition : rpcs) { - String resourcePath = "/operations/" + m.getName() + ":"; - addRpcs(rpcDefinition, apis, resourcePath); + } + _logger.debug("Number of APIs found [{}]", apis.size()); + doc.setApis(apis); + JSONObject models = null; + + try { + models = jsonConverter.convertToJsonSchema(m); + doc.setModels(models); + _logger.debug(mapper.writeValueAsString(doc)); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + return doc; } - _logger.debug("Number of APIs found [{}]", apis.size()); - doc.setApis(apis); - JSONObject models = null; - - try { - models = jsonConverter.convertToJsonSchema(m); - doc.setModels(models); - _logger.debug(mapper.writeValueAsString(doc)); - } catch (IOException | JSONException e) { - e.printStackTrace(); + + private String generateCacheKey(final Module m) { + return generateCacheKey(m.getName(), SIMPLE_DATE_FORMAT.format(m.getRevision())); } - return doc; - } - - private String generateCacheKey(Module m) { - return generateCacheKey(m.getName(), SIMPLE_DATE_FORMAT.format(m.getRevision())); - } - - private String generateCacheKey(String module, String revision) { - return module + "," + revision; - } - - private void addApis(DataSchemaNode node, - List apis, - String parentPath, - List parentPathParams, - boolean addConfigApi) { - - Api api = new Api(); - List pathParams = new ArrayList(parentPathParams); - - String resourcePath = parentPath + createPath(node, pathParams) + "/"; - _logger.debug("Adding path: [{}]", resourcePath); - api.setPath(resourcePath); - api.setOperations(operations(node, pathParams, addConfigApi)); - apis.add(api); - if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) { - DataNodeContainer schemaNode = (DataNodeContainer) node; - Set dataSchemaNodes = schemaNode.getChildNodes(); - - for (DataSchemaNode childNode : dataSchemaNodes) { - addApis(childNode, apis, resourcePath, pathParams, addConfigApi); - } + private String generateCacheKey(final String module, final String revision) { + return module + "," + revision; } - } + private void addApis(final DataSchemaNode node, + final List apis, + final String parentPath, + final List parentPathParams, + final boolean addConfigApi) { + + Api api = new Api(); + List pathParams = new ArrayList(parentPathParams); + + String resourcePath = parentPath + createPath(node, pathParams) + "/"; + _logger.debug("Adding path: [{}]", resourcePath); + api.setPath(resourcePath); + api.setOperations(operations(node, pathParams, addConfigApi)); + apis.add(api); + if ((node instanceof ListSchemaNode) || (node instanceof ContainerSchemaNode)) { + DataNodeContainer schemaNode = (DataNodeContainer) node; + Set dataSchemaNodes = schemaNode.getChildNodes(); + + for (DataSchemaNode childNode : dataSchemaNodes) { + addApis(childNode, apis, resourcePath, pathParams, addConfigApi); + } + } - private void addRpcs(RpcDefinition rpcDefn, List apis, String parentPath) { - Api rpc = new Api(); - String resourcePath = parentPath + rpcDefn.getQName().getLocalName(); - rpc.setPath(resourcePath); + } + + private void addRpcs(final RpcDefinition rpcDefn, final List apis, final String parentPath) { + Api rpc = new Api(); + String resourcePath = parentPath + rpcDefn.getQName().getLocalName(); + rpc.setPath(resourcePath); - Operation operationSpec = new Operation(); - operationSpec.setMethod("POST"); - operationSpec.setNotes(rpcDefn.getDescription()); - operationSpec.setNickname(rpcDefn.getQName().getLocalName()); - rpc.setOperations(Arrays.asList(operationSpec)); + Operation operationSpec = new Operation(); + operationSpec.setMethod("POST"); + operationSpec.setNotes(rpcDefn.getDescription()); + operationSpec.setNickname(rpcDefn.getQName().getLocalName()); + rpc.setOperations(Arrays.asList(operationSpec)); - apis.add(rpc); - } + apis.add(rpc); + } - /** - * @param node - * @param pathParams - * @return - */ - private List operations(DataSchemaNode node, List pathParams, boolean isConfig) { - List operations = new ArrayList<>(); + /** + * @param node + * @param pathParams + * @return + */ + private List operations(final DataSchemaNode node, final List pathParams, final boolean isConfig) { + List operations = new ArrayList<>(); - OperationBuilder.Get getBuilder = new OperationBuilder.Get(node); - operations.add(getBuilder.pathParams(pathParams).build()); + OperationBuilder.Get getBuilder = new OperationBuilder.Get(node); + operations.add(getBuilder.pathParams(pathParams).build()); - if (isConfig) { - OperationBuilder.Post postBuilder = new OperationBuilder.Post(node); - operations.add(postBuilder.pathParams(pathParams).build()); + if (isConfig) { + OperationBuilder.Post postBuilder = new OperationBuilder.Post(node); + operations.add(postBuilder.pathParams(pathParams).build()); - OperationBuilder.Put putBuilder = new OperationBuilder.Put(node); - operations.add(putBuilder.pathParams(pathParams).build()); + OperationBuilder.Put putBuilder = new OperationBuilder.Put(node); + operations.add(putBuilder.pathParams(pathParams).build()); - OperationBuilder.Delete deleteBuilder = new OperationBuilder.Delete(node); - operations.add(deleteBuilder.pathParams(pathParams).build()); + OperationBuilder.Delete deleteBuilder = new OperationBuilder.Delete(node); + operations.add(deleteBuilder.pathParams(pathParams).build()); + } + return operations; } - return operations; - } - - private String createPath(final DataSchemaNode schemaNode, List pathParams) { - ArrayList pathListParams = new ArrayList(); - StringBuilder path = new StringBuilder(); - QName _qName = schemaNode.getQName(); - String localName = _qName.getLocalName(); - path.append(localName); - - if ((schemaNode instanceof ListSchemaNode)) { - final List 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); + + private String createPath(final DataSchemaNode schemaNode, final List pathParams) { + ArrayList pathListParams = new ArrayList(); + StringBuilder path = new StringBuilder(); + QName _qName = schemaNode.getQName(); + String localName = _qName.getLocalName(); + path.append(localName); + + if ((schemaNode instanceof ListSchemaNode)) { + final List 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); + } + } } - } + return path.toString(); } - return path.toString(); - } }