Change alignments in methods declaration
[netconf.git] / restconf / sal-rest-docgen / src / main / java / org / opendaylight / netconf / sal / rest / doc / mountpoints / MountPointSwagger.java
index e81d1e5c158c37d56ba25bc6978704e100f7ac17..5287d7e675026acfee1e5f551d523f15f8bb3ffe 100644 (file)
@@ -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,42 +7,57 @@
  */
 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.Optional;
 import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
+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.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
+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.yangtools.yang.common.QName;
+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.NodeIdentifierWithPredicates;
 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 extends BaseYangSwaggerGenerator implements MountProvisionListener {
+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";
-    private static final AtomicReference<MountPointSwagger> SELF_REF = new AtomicReference<>();
 
-    private DOMMountPointService mountService;
+    private final DOMSchemaService globalSchema;
+    private final DOMMountPointService mountService;
+    private final BaseYangSwaggerGenerator swaggerGenerator;
     private final Map<YangInstanceIdentifier, Long> instanceIdToLongId =
             new TreeMap<>((o1, o2) -> o1.toString().compareToIgnoreCase(o2.toString()));
     private final Map<Long, YangInstanceIdentifier> longIdToInstanceId = new HashMap<>();
@@ -50,195 +65,198 @@ public class MountPointSwagger extends BaseYangSwaggerGenerator implements Mount
     private final Object lock = new Object();
 
     private final AtomicLong idKey = new AtomicLong(0);
-    private SchemaService globalSchema;
+
+    private ListenerRegistration<DOMMountPointListener> registration;
+
+    public MountPointSwagger(final DOMSchemaService globalSchema, final DOMMountPointService mountService,
+            final BaseYangSwaggerGenerator swaggerGenerator) {
+        this.globalSchema = requireNonNull(globalSchema);
+        this.mountService = requireNonNull(mountService);
+        this.swaggerGenerator = requireNonNull(swaggerGenerator);
+    }
+
+    public void init() {
+        registration = mountService.registerProvisionListener(this);
+    }
+
+    @Override
+    public void close() {
+        if (registration != null) {
+            registration.close();
+        }
+    }
 
     public Map<String, Long> getInstanceIdentifiers() {
-        Preconditions.checkState(globalSchema != null);
         final Map<String, Long> urlToId = new HashMap<>();
-        synchronized (this.lock) {
-            final SchemaContext context = this.globalSchema.getGlobalContext();
-            for (final Entry<YangInstanceIdentifier, Long> entry : this.instanceIdToLongId.entrySet()) {
+        synchronized (lock) {
+            final SchemaContext context = globalSchema.getGlobalContext();
+            for (final Entry<YangInstanceIdentifier, Long> entry : instanceIdToLongId.entrySet()) {
                 final String modName = findModuleName(entry.getKey(), context);
-                urlToId.put(generateUrlPrefixFromInstanceID(entry.getKey(), modName), entry.getValue());
+                urlToId.put(swaggerGenerator.generateUrlPrefixFromInstanceID(entry.getKey(), modName),
+                        entry.getValue());
             }
         }
         return urlToId;
     }
 
-    public void setGlobalSchema(final SchemaService globalSchema) {
-        this.globalSchema = globalSchema;
-    }
-
-    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();
             }
         }
         return null;
     }
 
-    private String generateUrlPrefixFromInstanceID(final YangInstanceIdentifier key, final String moduleName) {
-        final StringBuilder builder = new StringBuilder();
-        builder.append("/");
-        if (moduleName != null) {
-            builder.append(moduleName).append(':');
-        }
-        for (final PathArgument arg : key.getPathArguments()) {
-            final String name = arg.getNodeType().getLocalName();
-            if (arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
-                final NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
-                for (final Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
-                    if (isNewDraft()) {
-                        builder.deleteCharAt(builder.length() - 1).append("=").append(entry.getValue()).append('/');
-                    } else {
-                        builder.append(entry.getValue()).append('/');
-                    }
-                }
-            } else {
-                builder.append(name).append('/');
-            }
-        }
-        return builder.toString();
-    }
-
     private String getYangMountUrl(final YangInstanceIdentifier key) {
-        Preconditions.checkState(globalSchema != null);
-        final String modName = findModuleName(key, this.globalSchema.getGlobalContext());
-        return 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 createResourceList();
-        }
-        final List<Resource> resources = new LinkedList<>();
-        final Resource dataStores = new Resource();
-        dataStores.setDescription("Provides methods for accessing the data stores.");
-        dataStores.setPath(generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
-        resources.add(dataStores);
-        final String urlPrefix = getYangMountUrl(iid);
-        final ResourceList list = super.getResourceListing(uriInfo, context, urlPrefix);
-        resources.addAll(list.getApis());
-        list.setApis(resources);
-        return list;
+        final String modName = findModuleName(key, globalSchema.getGlobalContext());
+        return swaggerGenerator.generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount";
     }
 
     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<DOMMountPoint> 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<Integer> 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<Integer>> 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 super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
-    }
 
-    private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
-        final List<Api> 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 SwaggerObject doc;
 
-        final ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
-        declaration.setApis(apis);
-        return declaration;
+        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 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 static String extractDeviceName(final YangInstanceIdentifier iid) {
+        return ((YangInstanceIdentifier.NodeIdentifierWithPredicates.Singleton)iid.getLastPathArgument())
+                .values().getElement().toString();
+    }
 
-        final Api api = new Api();
-        api.setPath(getDataStorePath(datastore, context).concat(getContent(datastore)));
-        api.setOperations(Collections.singletonList(getConfig));
+    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 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 api;
+        return declaration;
     }
 
-    public void setMountService(final DOMMountPointService mountService) {
-        this.mountService = mountService;
+    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);
         }
     }
-
-    public static MountPointSwagger getInstance() {
-        MountPointSwagger swagger = SELF_REF.get();
-        if (swagger == null) {
-            SELF_REF.compareAndSet(null, new MountPointSwagger());
-            swagger = SELF_REF.get();
-        }
-
-        swagger.setDraft(false);
-        return swagger;
-    }
-
-    public static MountPointSwagger getInstanceDraft18() {
-        MountPointSwagger swagger = SELF_REF.get();
-        if (swagger == null) {
-            SELF_REF.compareAndSet(null, new MountPointSwagger());
-            swagger = SELF_REF.get();
-        }
-
-        swagger.setDraft(true);
-        return swagger;
-    }
 }