X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Fsal-rest-docgen%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Frest%2Fdoc%2Fmountpoints%2FMountPointSwagger.java;h=5287d7e675026acfee1e5f551d523f15f8bb3ffe;hb=c5b2232060e8e14ae1213a8c017c50a5eff8681f;hp=df9fca6d258d32c2bcd8a5444cbee82ae4fee6e6;hpb=edf3b06cb4e53a91f3756663dfbea9a1eb9154d1;p=netconf.git diff --git a/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/mountpoints/MountPointSwagger.java b/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/mountpoints/MountPointSwagger.java index df9fca6d25..5287d7e675 100644 --- a/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/mountpoints/MountPointSwagger.java +++ b/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/mountpoints/MountPointSwagger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved. + * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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, @@ -7,36 +7,51 @@ */ package org.opendaylight.netconf.sal.rest.doc.mountpoints; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import java.util.Collections; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.netconf.sal.rest.doc.impl.ApiDocServiceImpl.DEFAULT_PAGESIZE; +import static org.opendaylight.netconf.sal.rest.doc.impl.BaseYangSwaggerGenerator.BASE_PATH; +import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.DESCRIPTION_KEY; +import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.RESPONSES_KEY; +import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.SUMMARY_KEY; +import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.SUMMARY_SEPARATOR; +import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.TAGS_KEY; +import static org.opendaylight.netconf.sal.rest.doc.model.builder.OperationBuilder.buildTagsValue; +import static org.opendaylight.netconf.sal.rest.doc.util.JsonUtil.addFields; + +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.Range; import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; +import java.util.Optional; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicLong; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; -import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.mdsal.dom.api.DOMMountPointListener; +import org.opendaylight.mdsal.dom.api.DOMMountPointService; import org.opendaylight.mdsal.dom.api.DOMSchemaService; +import org.opendaylight.netconf.sal.rest.doc.impl.ApiDocServiceImpl.OAversion; import org.opendaylight.netconf.sal.rest.doc.impl.BaseYangSwaggerGenerator; -import org.opendaylight.netconf.sal.rest.doc.swagger.Api; -import org.opendaylight.netconf.sal.rest.doc.swagger.ApiDeclaration; -import org.opendaylight.netconf.sal.rest.doc.swagger.Operation; -import org.opendaylight.netconf.sal.rest.doc.swagger.Resource; -import org.opendaylight.netconf.sal.rest.doc.swagger.ResourceList; +import org.opendaylight.netconf.sal.rest.doc.impl.DefinitionNames; +import org.opendaylight.netconf.sal.rest.doc.swagger.CommonApiObject; +import org.opendaylight.netconf.sal.rest.doc.swagger.SwaggerObject; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class MountPointSwagger implements DOMMountPointListener, AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(MountPointSwagger.class); + private static final String DATASTORES_REVISION = "-"; private static final String DATASTORES_LABEL = "Datastores"; @@ -55,9 +70,9 @@ public class MountPointSwagger implements DOMMountPointListener, AutoCloseable { public MountPointSwagger(final DOMSchemaService globalSchema, final DOMMountPointService mountService, final BaseYangSwaggerGenerator swaggerGenerator) { - this.globalSchema = Objects.requireNonNull(globalSchema); - this.mountService = Objects.requireNonNull(mountService); - this.swaggerGenerator = Objects.requireNonNull(swaggerGenerator); + this.globalSchema = requireNonNull(globalSchema); + this.mountService = requireNonNull(mountService); + this.swaggerGenerator = requireNonNull(swaggerGenerator); } public void init() { @@ -73,9 +88,9 @@ public class MountPointSwagger implements DOMMountPointListener, AutoCloseable { public Map getInstanceIdentifiers() { final Map urlToId = new HashMap<>(); - synchronized (this.lock) { - final SchemaContext context = this.globalSchema.getGlobalContext(); - for (final Entry entry : this.instanceIdToLongId.entrySet()) { + synchronized (lock) { + final SchemaContext context = globalSchema.getGlobalContext(); + for (final Entry entry : instanceIdToLongId.entrySet()) { final String modName = findModuleName(entry.getKey(), context); urlToId.put(swaggerGenerator.generateUrlPrefixFromInstanceID(entry.getKey(), modName), entry.getValue()); @@ -84,10 +99,10 @@ public class MountPointSwagger implements DOMMountPointListener, AutoCloseable { return urlToId; } - private String findModuleName(final YangInstanceIdentifier id, final SchemaContext context) { + private static String findModuleName(final YangInstanceIdentifier id, final SchemaContext context) { final PathArgument rootQName = id.getPathArguments().iterator().next(); for (final Module mod : context.getModules()) { - if (mod.getDataChildByName(rootQName.getNodeType()) != null) { + if (mod.findDataChildByName(rootQName.getNodeType()).isPresent()) { return mod.getName(); } } @@ -95,116 +110,153 @@ public class MountPointSwagger implements DOMMountPointListener, AutoCloseable { } private String getYangMountUrl(final YangInstanceIdentifier key) { - final String modName = findModuleName(key, this.globalSchema.getGlobalContext()); + final String modName = findModuleName(key, globalSchema.getGlobalContext()); return swaggerGenerator.generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount"; } - public ResourceList getResourceList(final UriInfo uriInfo, final Long id) { - final YangInstanceIdentifier iid = getInstanceId(id); - if (iid == null) { - return null; // indicating not found. - } - final SchemaContext context = getSchemaContext(iid); - if (context == null) { - return swaggerGenerator.createResourceList(); - } - final List resources = new LinkedList<>(); - final Resource dataStores = new Resource(); - dataStores.setDescription("Provides methods for accessing the data stores."); - dataStores.setPath(swaggerGenerator.generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION)); - resources.add(dataStores); - final String urlPrefix = getYangMountUrl(iid); - final ResourceList list = swaggerGenerator.getResourceListing(uriInfo, context, urlPrefix); - resources.addAll(list.getApis()); - list.setApis(resources); - return list; - } - private YangInstanceIdentifier getInstanceId(final Long id) { final YangInstanceIdentifier instanceId; - synchronized (this.lock) { - instanceId = this.longIdToInstanceId.get(id); + synchronized (lock) { + instanceId = longIdToInstanceId.get(id); } return instanceId; } - private SchemaContext getSchemaContext(final YangInstanceIdentifier id) { - + private EffectiveModelContext getSchemaContext(final YangInstanceIdentifier id) { if (id == null) { return null; } - Preconditions.checkState(mountService != null); - final Optional mountPoint = this.mountService.getMountPoint(id); - if (!mountPoint.isPresent()) { - return null; - } + checkState(mountService != null); + return mountService.getMountPoint(id) + .flatMap(mountPoint -> mountPoint.getService(DOMSchemaService.class)) + .flatMap(svc -> Optional.ofNullable(svc.getGlobalContext())) + .orElse(null); + } + + public CommonApiObject getMountPointApi(final UriInfo uriInfo, final Long id, final String module, + final String revision, final OAversion oaversion) { + final YangInstanceIdentifier iid = getInstanceId(id); + final EffectiveModelContext context = getSchemaContext(iid); + final String urlPrefix = getYangMountUrl(iid); + final String deviceName = extractDeviceName(iid); - final SchemaContext context = mountPoint.get().getSchemaContext(); if (context == null) { return null; } - return context; + + if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) { + return generateDataStoreApiDoc(uriInfo, urlPrefix, deviceName); + } + final SwaggerObject swaggerObject = swaggerGenerator.getApiDeclaration(module, revision, uriInfo, context, + urlPrefix, oaversion); + return BaseYangSwaggerGenerator.getAppropriateDoc(swaggerObject, oaversion); } - public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module, - final String revision) { + public CommonApiObject getMountPointApi(final UriInfo uriInfo, final Long id, final Optional pageNum, + final OAversion oaversion) { final YangInstanceIdentifier iid = getInstanceId(id); - final SchemaContext context = getSchemaContext(iid); + final EffectiveModelContext context = getSchemaContext(iid); final String urlPrefix = getYangMountUrl(iid); + final String deviceName = extractDeviceName(iid); + if (context == null) { return null; } + final DefinitionNames definitionNames = new DefinitionNames(); - if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) { - return generateDataStoreApiDoc(uriInfo, urlPrefix); + boolean includeDataStore = true; + Optional> range = Optional.empty(); + + if (pageNum.isPresent()) { + final int pageNumValue = pageNum.get(); + final int end = DEFAULT_PAGESIZE * pageNumValue - 1; + int start = end - DEFAULT_PAGESIZE; + if (pageNumValue == 1) { + start++; + } else { + includeDataStore = false; + } + range = Optional.of(Range.closed(start, end)); } - return swaggerGenerator.getApiDeclaration(module, revision, uriInfo, context, urlPrefix); - } - private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) { - final List apis = new LinkedList<>(); - apis.add(createGetApi("config", "Queries the config (startup) datastore on the mounted hosted.", context)); - apis.add(createGetApi("operational", "Queries the operational (running) datastore on the mounted hosted.", - context)); - apis.add(createGetApi("operations", "Queries the available operations (RPC calls) on the mounted hosted.", - context)); - - final ApiDeclaration declaration = swaggerGenerator.createApiDeclaration( - swaggerGenerator.createBasePathFromUriInfo(uriInfo)); - declaration.setApis(apis); - return declaration; + final SwaggerObject doc; + + final SwaggerObject swaggerObject = swaggerGenerator.getAllModulesDoc(uriInfo, range, context, + Optional.of(deviceName), urlPrefix, definitionNames, oaversion); + if (includeDataStore) { + doc = generateDataStoreApiDoc(uriInfo, urlPrefix, deviceName); + addFields(doc.getPaths() ,swaggerObject.getPaths().fields()); + addFields(doc.getDefinitions() ,swaggerObject.getDefinitions().fields()); + doc.getInfo().setTitle(swaggerObject.getInfo().getTitle()); + } else { + doc = swaggerObject; + } + + return BaseYangSwaggerGenerator.getAppropriateDoc(doc, oaversion); + } + + private static String extractDeviceName(final YangInstanceIdentifier iid) { + return ((YangInstanceIdentifier.NodeIdentifierWithPredicates.Singleton)iid.getLastPathArgument()) + .values().getElement().toString(); } - private Api createGetApi(final String datastore, final String note, final String context) { - final Operation getConfig = new Operation(); - getConfig.setMethod("GET"); - getConfig.setNickname("GET " + datastore); - getConfig.setNotes(note); + private SwaggerObject generateDataStoreApiDoc(final UriInfo uriInfo, final String context, + final String deviceName) { + final SwaggerObject declaration = swaggerGenerator.createSwaggerObject( + swaggerGenerator.createSchemaFromUriInfo(uriInfo), + swaggerGenerator.createHostFromUriInfo(uriInfo), + BASE_PATH, + context); - final Api api = new Api(); - api.setPath(swaggerGenerator.getDataStorePath(datastore, context).concat( - swaggerGenerator.getContent(datastore))); - api.setOperations(Collections.singletonList(getConfig)); + final ObjectNode pathsObject = JsonNodeFactory.instance.objectNode(); + createGetPathItem("config", "Queries the config (startup) datastore on the mounted hosted.", + context, deviceName, pathsObject); + createGetPathItem("operational", "Queries the operational (running) datastore on the mounted hosted.", + context, deviceName, pathsObject); + createGetPathItem("operations", "Queries the available operations (RPC calls) on the mounted hosted.", + context, deviceName, pathsObject); + + declaration.setPaths(pathsObject); + declaration.setDefinitions(JsonNodeFactory.instance.objectNode()); + + return declaration; + } - return api; + private void createGetPathItem(final String resourceType, final String description, final String context, + final String deviceName, final ObjectNode pathsObject) { + final ObjectNode pathItem = JsonNodeFactory.instance.objectNode(); + final ObjectNode operationObject = JsonNodeFactory.instance.objectNode(); + pathItem.set("get", operationObject); + operationObject.put(DESCRIPTION_KEY, description); + operationObject.put(SUMMARY_KEY, HttpMethod.GET + SUMMARY_SEPARATOR + deviceName + SUMMARY_SEPARATOR + + swaggerGenerator.getResourcePathPart(resourceType)); + operationObject.set(TAGS_KEY, buildTagsValue(Optional.of(deviceName), "GET root")); + final ObjectNode okResponse = JsonNodeFactory.instance.objectNode(); + okResponse.put(DESCRIPTION_KEY, Response.Status.OK.getReasonPhrase()); + final ObjectNode responses = JsonNodeFactory.instance.objectNode(); + responses.set(String.valueOf(Response.Status.OK.getStatusCode()), okResponse); + operationObject.set(RESPONSES_KEY, responses); + pathsObject.set(swaggerGenerator.getResourcePath(resourceType, context), pathItem); } @Override public void onMountPointCreated(final YangInstanceIdentifier path) { - synchronized (this.lock) { - final Long idLong = this.idKey.incrementAndGet(); - this.instanceIdToLongId.put(path, idLong); - this.longIdToInstanceId.put(idLong, path); + synchronized (lock) { + LOG.debug("Mount point {} created", path); + final Long idLong = idKey.incrementAndGet(); + instanceIdToLongId.put(path, idLong); + longIdToInstanceId.put(idLong, path); } } @Override public void onMountPointRemoved(final YangInstanceIdentifier path) { - synchronized (this.lock) { - final Long id = this.instanceIdToLongId.remove(path); - this.longIdToInstanceId.remove(id); + synchronized (lock) { + LOG.debug("Mount point {} removed", path); + final Long id = instanceIdToLongId.remove(path); + longIdToInstanceId.remove(id); } } }