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.controller.sal.rest.doc.mountpoints;
10 import com.google.common.base.Optional;
11 import java.util.Collections;
12 import java.util.Comparator;
13 import java.util.HashMap;
14 import java.util.LinkedList;
15 import java.util.List;
17 import java.util.Map.Entry;
18 import java.util.TreeMap;
19 import java.util.concurrent.atomic.AtomicLong;
20 import java.util.concurrent.atomic.AtomicReference;
21 import javax.ws.rs.core.UriInfo;
22 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
23 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
24 import org.opendaylight.controller.sal.core.api.model.SchemaService;
25 import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
26 import org.opendaylight.controller.sal.rest.doc.impl.BaseYangSwaggerGenerator;
27 import org.opendaylight.controller.sal.rest.doc.swagger.Api;
28 import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
29 import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
30 import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
31 import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
32 import org.opendaylight.yangtools.yang.common.QName;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
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 extends BaseYangSwaggerGenerator implements MountProvisionListener {
41 private static final String DATASTORES_REVISION = "-";
42 private static final String DATASTORES_LABEL = "Datastores";
44 private DOMMountPointService mountService;
45 private final Map<YangInstanceIdentifier, Long> instanceIdToLongId = new TreeMap<>(
46 new Comparator<YangInstanceIdentifier>() {
48 public int compare(final YangInstanceIdentifier o1, final YangInstanceIdentifier o2) {
49 return o1.toString().compareToIgnoreCase(o2.toString());
52 private final Map<Long, YangInstanceIdentifier> longIdToInstanceId = new HashMap<>();
53 private final Object lock = new Object();
55 private final AtomicLong idKey = new AtomicLong(0);
57 private static AtomicReference<MountPointSwagger> selfRef = new AtomicReference<>();
58 private SchemaService globalSchema;
60 public Map<String, Long> getInstanceIdentifiers() {
61 Map<String, Long> urlToId = new HashMap<>();
63 SchemaContext context = globalSchema.getGlobalContext();
64 for (Entry<YangInstanceIdentifier, Long> entry : instanceIdToLongId.entrySet()) {
65 String modName = findModuleName(entry.getKey(), context);
66 urlToId.put(generateUrlPrefixFromInstanceID(entry.getKey(), modName),
73 public void setGlobalSchema(final SchemaService globalSchema) {
74 this.globalSchema = globalSchema;
77 private String findModuleName(final YangInstanceIdentifier id, final SchemaContext context) {
78 PathArgument rootQName = id.getPathArguments().iterator().next();
79 for (Module mod : context.getModules()) {
80 if (mod.getDataChildByName(rootQName.getNodeType()) != null) {
87 private String generateUrlPrefixFromInstanceID(final YangInstanceIdentifier key, final String moduleName) {
88 StringBuilder builder = new StringBuilder();
89 if (moduleName != null) {
90 builder.append(moduleName);
94 for (PathArgument arg : key.getPathArguments()) {
96 String name = arg.getNodeType().getLocalName();
102 builder.append(name);
103 if (arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
104 NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
105 for (Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
106 builder.append('/').append(entry.getValue());
111 return builder.append('/').toString();
114 private String getYangMountUrl(final YangInstanceIdentifier key) {
115 String modName = findModuleName(key, globalSchema.getGlobalContext());
116 return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount/";
119 public ResourceList getResourceList(final UriInfo uriInfo, final Long id) {
120 YangInstanceIdentifier iid = getInstanceId(id);
122 return null; // indicating not found.
124 SchemaContext context = getSchemaContext(iid);
125 String urlPrefix = getYangMountUrl(iid);
126 if (context == null) {
127 return createResourceList();
129 List<Resource> resources = new LinkedList<>();
130 Resource dataStores = new Resource();
131 dataStores.setDescription("Provides methods for accessing the data stores.");
132 dataStores.setPath(generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
133 resources.add(dataStores);
134 ResourceList list = super.getResourceListing(uriInfo, context, urlPrefix);
135 resources.addAll(list.getApis());
136 list.setApis(resources);
140 private YangInstanceIdentifier getInstanceId(final Long id) {
141 YangInstanceIdentifier instanceId;
142 synchronized (lock) {
143 instanceId = longIdToInstanceId.get(id);
148 private SchemaContext getSchemaContext(final YangInstanceIdentifier id) {
154 Optional<DOMMountPoint> mountPoint = mountService.getMountPoint(id);
155 if (!mountPoint.isPresent()) {
159 SchemaContext context = mountPoint.get().getSchemaContext();
160 if (context == null) {
166 public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module, final String revision) {
167 YangInstanceIdentifier iid = getInstanceId(id);
168 SchemaContext context = getSchemaContext(iid);
169 String urlPrefix = getYangMountUrl(iid);
170 if (context == null) {
174 if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) {
175 return generateDataStoreApiDoc(uriInfo, urlPrefix);
177 return super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
180 private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
182 ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
183 List<Api> apis = new LinkedList<>();
184 apis.add(createGetApi("config",
185 "Queries the config (startup) datastore on the mounted hosted.", context));
186 apis.add(createGetApi("operational",
187 "Queries the operational (running) datastore on the mounted hosted.", context));
188 apis.add(createGetApi("operations",
189 "Queries the available operations (RPC calls) on the mounted hosted.", context));
190 declaration.setApis(apis);
195 private Api createGetApi(final String datastore, final String note, final String context) {
196 Operation getConfig = new Operation();
197 getConfig.setMethod("GET");
198 getConfig.setNickname("GET " + datastore);
199 getConfig.setNotes(note);
202 api.setPath(getDataStorePath("/" + datastore + "/", context));
203 api.setOperations(Collections.singletonList(getConfig));
208 public void setMountService(final DOMMountPointService mountService) {
209 this.mountService = mountService;
213 public void onMountPointCreated(final YangInstanceIdentifier path) {
214 synchronized (lock) {
215 Long idLong = idKey.incrementAndGet();
216 instanceIdToLongId.put(path, idLong);
217 longIdToInstanceId.put(idLong, path);
222 public void onMountPointRemoved(final YangInstanceIdentifier path) {
223 synchronized (lock) {
224 Long id = instanceIdToLongId.remove(path);
225 longIdToInstanceId.remove(id);
229 public static MountPointSwagger getInstance() {
230 MountPointSwagger swagger = selfRef.get();
231 if (swagger == null) {
232 selfRef.compareAndSet(null, new MountPointSwagger());
233 swagger = selfRef.get();