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 java.util.Collections;
11 import java.util.Comparator;
12 import java.util.HashMap;
13 import java.util.LinkedList;
14 import java.util.List;
16 import java.util.Map.Entry;
17 import java.util.TreeMap;
18 import java.util.concurrent.atomic.AtomicLong;
19 import java.util.concurrent.atomic.AtomicReference;
21 import javax.ws.rs.core.UriInfo;
23 import org.opendaylight.controller.sal.core.api.model.SchemaService;
24 import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
25 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
26 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService.MountProvisionListener;
27 import org.opendaylight.controller.sal.rest.doc.impl.BaseYangSwaggerGenerator;
28 import org.opendaylight.controller.sal.rest.doc.swagger.Api;
29 import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
30 import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
31 import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
32 import org.opendaylight.controller.sal.rest.doc.swagger.ResourceList;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
36 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
37 import org.opendaylight.yangtools.yang.model.api.Module;
38 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
40 public class MountPointSwagger extends BaseYangSwaggerGenerator implements MountProvisionListener {
42 private static final String DATASTORES_REVISION = "-";
43 private static final String DATASTORES_LABEL = "Datastores";
45 private MountProvisionService mountService;
46 private final Map<InstanceIdentifier, Long> instanceIdToLongId = new TreeMap<>(
47 new Comparator<InstanceIdentifier>() {
49 public int compare(final InstanceIdentifier o1, final InstanceIdentifier o2) {
50 return o1.toString().compareToIgnoreCase(o2.toString());
53 private final Map<Long, InstanceIdentifier> longIdToInstanceId = new HashMap<>();
54 private final Object lock = new Object();
56 private final AtomicLong idKey = new AtomicLong(0);
58 private static AtomicReference<MountPointSwagger> selfRef = new AtomicReference<>();
59 private SchemaService globalSchema;
61 public Map<String, Long> getInstanceIdentifiers() {
62 Map<String, Long> urlToId = new HashMap<>();
64 SchemaContext context = globalSchema.getGlobalContext();
65 for (Entry<InstanceIdentifier, Long> entry : instanceIdToLongId.entrySet()) {
66 String modName = findModuleName(entry.getKey(), context);
67 urlToId.put(generateUrlPrefixFromInstanceID(entry.getKey(), modName),
74 public void setGlobalSchema(final SchemaService globalSchema) {
75 this.globalSchema = globalSchema;
78 private String findModuleName(final InstanceIdentifier id, final SchemaContext context) {
79 PathArgument rootQName = id.getPathArguments().iterator().next();
80 for (Module mod : context.getModules()) {
81 if (mod.getDataChildByName(rootQName.getNodeType()) != null) {
88 private String generateUrlPrefixFromInstanceID(final InstanceIdentifier key, final String moduleName) {
89 StringBuilder builder = new StringBuilder();
90 if (moduleName != null) {
91 builder.append(moduleName);
95 for (PathArgument arg : key.getPathArguments()) {
97 String name = arg.getNodeType().getLocalName();
103 builder.append(name);
104 if (arg instanceof InstanceIdentifier.NodeIdentifierWithPredicates) {
105 NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
106 for (Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
107 builder.append('/').append(entry.getValue());
112 return builder.append('/').toString();
115 private String getYangMountUrl(final InstanceIdentifier key) {
116 String modName = findModuleName(key, globalSchema.getGlobalContext());
117 return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount/";
120 public ResourceList getResourceList(final UriInfo uriInfo, final Long id) {
121 InstanceIdentifier iid = getInstanceId(id);
123 return null; // indicating not found.
125 SchemaContext context = getSchemaContext(iid);
126 String urlPrefix = getYangMountUrl(iid);
127 if (context == null) {
128 return createResourceList();
130 List<Resource> resources = new LinkedList<>();
131 Resource dataStores = new Resource();
132 dataStores.setDescription("Provides methods for accessing the data stores.");
133 dataStores.setPath(generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
134 resources.add(dataStores);
135 ResourceList list = super.getResourceListing(uriInfo, context, urlPrefix);
136 resources.addAll(list.getApis());
137 list.setApis(resources);
141 private InstanceIdentifier getInstanceId(final Long id) {
142 InstanceIdentifier instanceId;
143 synchronized (lock) {
144 instanceId = longIdToInstanceId.get(id);
149 private SchemaContext getSchemaContext(final InstanceIdentifier id) {
155 MountProvisionInstance mountPoint = mountService.getMountPoint(id);
156 if (mountPoint == null) {
160 SchemaContext context = mountPoint.getSchemaContext();
161 if (context == null) {
167 public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module, final String revision) {
168 InstanceIdentifier iid = getInstanceId(id);
169 SchemaContext context = getSchemaContext(iid);
170 String urlPrefix = getYangMountUrl(iid);
171 if (context == null) {
175 if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) {
176 return generateDataStoreApiDoc(uriInfo, urlPrefix);
178 return super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
181 private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
183 ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
184 List<Api> apis = new LinkedList<>();
185 apis.add(createGetApi("config",
186 "Queries the config (startup) datastore on the mounted hosted.", context));
187 apis.add(createGetApi("operational",
188 "Queries the operational (running) datastore on the mounted hosted.", context));
189 apis.add(createGetApi("operations",
190 "Queries the available operations (RPC calls) on the mounted hosted.", context));
191 declaration.setApis(apis);
196 private Api createGetApi(final String datastore, final String note, final String context) {
197 Operation getConfig = new Operation();
198 getConfig.setMethod("GET");
199 getConfig.setNickname("GET " + datastore);
200 getConfig.setNotes(note);
203 api.setPath(getDataStorePath("/" + datastore + "/", context));
204 api.setOperations(Collections.singletonList(getConfig));
209 public void setMountService(final MountProvisionService mountService) {
210 this.mountService = mountService;
214 public void onMountPointCreated(final InstanceIdentifier path) {
215 synchronized (lock) {
216 Long idLong = idKey.incrementAndGet();
217 instanceIdToLongId.put(path, idLong);
218 longIdToInstanceId.put(idLong, path);
223 public void onMountPointRemoved(final InstanceIdentifier path) {
224 synchronized (lock) {
225 Long id = instanceIdToLongId.remove(path);
226 longIdToInstanceId.remove(id);
230 public static MountPointSwagger getInstance() {
231 MountPointSwagger swagger = selfRef.get();
232 if (swagger == null) {
233 selfRef.compareAndSet(null, new MountPointSwagger());
234 swagger = selfRef.get();