2 * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.sal.rest.doc.mountpoints;
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.LinkedList;
16 import java.util.List;
18 import java.util.Map.Entry;
19 import java.util.Optional;
20 import java.util.TreeMap;
21 import java.util.concurrent.atomic.AtomicLong;
22 import javax.ws.rs.core.UriInfo;
23 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
24 import org.opendaylight.mdsal.dom.api.DOMMountPointListener;
25 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
26 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
27 import org.opendaylight.netconf.sal.rest.doc.impl.BaseYangSwaggerGenerator;
28 import org.opendaylight.netconf.sal.rest.doc.swagger.Api;
29 import org.opendaylight.netconf.sal.rest.doc.swagger.ApiDeclaration;
30 import org.opendaylight.netconf.sal.rest.doc.swagger.Operation;
31 import org.opendaylight.netconf.sal.rest.doc.swagger.Resource;
32 import org.opendaylight.netconf.sal.rest.doc.swagger.ResourceList;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
36 import org.opendaylight.yangtools.yang.model.api.Module;
37 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
39 public class MountPointSwagger implements DOMMountPointListener, AutoCloseable {
41 private static final String DATASTORES_REVISION = "-";
42 private static final String DATASTORES_LABEL = "Datastores";
44 private final DOMSchemaService globalSchema;
45 private final DOMMountPointService mountService;
46 private final BaseYangSwaggerGenerator swaggerGenerator;
47 private final Map<YangInstanceIdentifier, Long> instanceIdToLongId =
48 new TreeMap<>((o1, o2) -> o1.toString().compareToIgnoreCase(o2.toString()));
49 private final Map<Long, YangInstanceIdentifier> longIdToInstanceId = new HashMap<>();
51 private final Object lock = new Object();
53 private final AtomicLong idKey = new AtomicLong(0);
55 private ListenerRegistration<DOMMountPointListener> registration;
57 public MountPointSwagger(final DOMSchemaService globalSchema, final DOMMountPointService mountService,
58 final BaseYangSwaggerGenerator swaggerGenerator) {
59 this.globalSchema = requireNonNull(globalSchema);
60 this.mountService = requireNonNull(mountService);
61 this.swaggerGenerator = requireNonNull(swaggerGenerator);
65 registration = mountService.registerProvisionListener(this);
70 if (registration != null) {
75 public Map<String, Long> getInstanceIdentifiers() {
76 final Map<String, Long> urlToId = new HashMap<>();
77 synchronized (this.lock) {
78 final SchemaContext context = this.globalSchema.getGlobalContext();
79 for (final Entry<YangInstanceIdentifier, Long> entry : this.instanceIdToLongId.entrySet()) {
80 final String modName = findModuleName(entry.getKey(), context);
81 urlToId.put(swaggerGenerator.generateUrlPrefixFromInstanceID(entry.getKey(), modName),
88 private static String findModuleName(final YangInstanceIdentifier id, final SchemaContext context) {
89 final PathArgument rootQName = id.getPathArguments().iterator().next();
90 for (final Module mod : context.getModules()) {
91 if (mod.findDataChildByName(rootQName.getNodeType()).isPresent()) {
98 private String getYangMountUrl(final YangInstanceIdentifier key) {
99 final String modName = findModuleName(key, this.globalSchema.getGlobalContext());
100 return swaggerGenerator.generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount";
103 public ResourceList getResourceList(final UriInfo uriInfo, final Long id) {
104 return getResourceList(uriInfo, id, 0, true);
107 public ResourceList getResourceList(final UriInfo uriInfo, final Long id, final int pageNum, boolean all) {
108 final YangInstanceIdentifier iid = getInstanceId(id);
110 return null; // indicating not found.
112 final SchemaContext context = getSchemaContext(iid);
113 if (context == null) {
114 return swaggerGenerator.createResourceList();
116 final List<Resource> resources = new LinkedList<>();
117 final Resource dataStores = new Resource();
118 dataStores.setDescription("Provides methods for accessing the data stores.");
119 dataStores.setPath(swaggerGenerator.generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
120 resources.add(dataStores);
121 final String urlPrefix = getYangMountUrl(iid);
122 final ResourceList list = swaggerGenerator.getResourceListing(uriInfo, context, urlPrefix, pageNum, all);
123 resources.addAll(list.getApis());
124 list.setApis(resources);
128 private YangInstanceIdentifier getInstanceId(final Long id) {
129 final YangInstanceIdentifier instanceId;
130 synchronized (this.lock) {
131 instanceId = this.longIdToInstanceId.get(id);
136 private SchemaContext getSchemaContext(final YangInstanceIdentifier id) {
141 checkState(mountService != null);
142 final Optional<DOMMountPoint> mountPoint = this.mountService.getMountPoint(id);
143 if (!mountPoint.isPresent()) {
147 final SchemaContext context = mountPoint.get().getSchemaContext();
148 if (context == null) {
154 public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module,
155 final String revision) {
156 final YangInstanceIdentifier iid = getInstanceId(id);
157 final SchemaContext context = getSchemaContext(iid);
158 final String urlPrefix = getYangMountUrl(iid);
159 if (context == null) {
163 if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) {
164 return generateDataStoreApiDoc(uriInfo, urlPrefix);
166 return swaggerGenerator.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
169 private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
170 final List<Api> apis = new LinkedList<>();
171 apis.add(createGetApi("config", "Queries the config (startup) datastore on the mounted hosted.", context));
172 apis.add(createGetApi("operational", "Queries the operational (running) datastore on the mounted hosted.",
174 apis.add(createGetApi("operations", "Queries the available operations (RPC calls) on the mounted hosted.",
177 final ApiDeclaration declaration = swaggerGenerator.createApiDeclaration(
178 swaggerGenerator.createBasePathFromUriInfo(uriInfo));
179 declaration.setApis(apis);
184 private Api createGetApi(final String datastore, final String note, final String context) {
185 final Operation getConfig = new Operation();
186 getConfig.setMethod("GET");
187 getConfig.setNickname("GET " + datastore);
188 getConfig.setNotes(note);
190 final Api api = new Api();
191 api.setPath(swaggerGenerator.getDataStorePath(datastore, context).concat(
192 swaggerGenerator.getContent(datastore)));
193 api.setOperations(Collections.singletonList(getConfig));
199 public void onMountPointCreated(final YangInstanceIdentifier path) {
200 synchronized (this.lock) {
201 final Long idLong = this.idKey.incrementAndGet();
202 this.instanceIdToLongId.put(path, idLong);
203 this.longIdToInstanceId.put(idLong, path);
208 public void onMountPointRemoved(final YangInstanceIdentifier path) {
209 synchronized (this.lock) {
210 final Long id = this.instanceIdToLongId.remove(path);
211 this.longIdToInstanceId.remove(id);