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 com.google.common.base.Optional;
11 import java.util.Collections;
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;
20 import javax.ws.rs.core.UriInfo;
21 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
22 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
23 import org.opendaylight.controller.sal.core.api.model.SchemaService;
24 import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
25 import org.opendaylight.netconf.sal.rest.doc.impl.BaseYangSwaggerGenerator;
26 import org.opendaylight.netconf.sal.rest.doc.swagger.Api;
27 import org.opendaylight.netconf.sal.rest.doc.swagger.ApiDeclaration;
28 import org.opendaylight.netconf.sal.rest.doc.swagger.Operation;
29 import org.opendaylight.netconf.sal.rest.doc.swagger.Resource;
30 import org.opendaylight.netconf.sal.rest.doc.swagger.ResourceList;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
35 import org.opendaylight.yangtools.yang.model.api.Module;
36 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38 public class MountPointSwagger extends BaseYangSwaggerGenerator implements MountProvisionListener {
40 private static final String DATASTORES_REVISION = "-";
41 private static final String DATASTORES_LABEL = "Datastores";
42 private static final String RESTCONF_DRAFT = "18";
44 private DOMMountPointService mountService;
45 private final Map<YangInstanceIdentifier, Long> instanceIdToLongId =
46 new TreeMap<>((o1, o2) -> o1.toString().compareToIgnoreCase(o2.toString()));
47 private final Map<Long, YangInstanceIdentifier> longIdToInstanceId = new HashMap<>();
48 private final Object lock = new Object();
50 private final AtomicLong idKey = new AtomicLong(0);
52 private static final AtomicReference<MountPointSwagger> selfRef = new AtomicReference<>();
53 private SchemaService globalSchema;
54 private static boolean newDraft;
56 public Map<String, Long> getInstanceIdentifiers() {
57 final Map<String, Long> urlToId = new HashMap<>();
58 synchronized (this.lock) {
59 final SchemaContext context = this.globalSchema.getGlobalContext();
60 for (final Entry<YangInstanceIdentifier, Long> entry : this.instanceIdToLongId.entrySet()) {
61 final String modName = findModuleName(entry.getKey(), context);
62 urlToId.put(generateUrlPrefixFromInstanceID(entry.getKey(), modName), entry.getValue());
68 public void setGlobalSchema(final SchemaService globalSchema) {
69 this.globalSchema = globalSchema;
72 private String findModuleName(final YangInstanceIdentifier id, final SchemaContext context) {
73 final PathArgument rootQName = id.getPathArguments().iterator().next();
74 for (final Module mod : context.getModules()) {
75 if (mod.getDataChildByName(rootQName.getNodeType()) != null) {
82 private String generateUrlPrefixFromInstanceID(final YangInstanceIdentifier key, final String moduleName) {
83 final StringBuilder builder = new StringBuilder();
85 if (moduleName != null) {
86 builder.append(moduleName).append(':');
88 for (final PathArgument arg : key.getPathArguments()) {
89 final String name = arg.getNodeType().getLocalName();
90 if (arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
91 final NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
92 for (final Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
94 builder.deleteCharAt(builder.length() - 1).append("=").append(entry.getValue()).append('/');
96 builder.append(entry.getValue()).append('/');
100 builder.append(name).append('/');
103 return builder.toString();
106 private String getYangMountUrl(final YangInstanceIdentifier key) {
107 final String modName = findModuleName(key, this.globalSchema.getGlobalContext());
108 return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount";
111 public ResourceList getResourceList(final UriInfo uriInfo, final Long id) {
112 final YangInstanceIdentifier iid = getInstanceId(id);
114 return null; // indicating not found.
116 final SchemaContext context = getSchemaContext(iid);
117 if (context == null) {
118 return createResourceList();
120 final List<Resource> resources = new LinkedList<>();
121 final Resource dataStores = new Resource();
122 dataStores.setDescription("Provides methods for accessing the data stores.");
123 dataStores.setPath(generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
124 resources.add(dataStores);
125 final String urlPrefix = getYangMountUrl(iid);
126 final ResourceList list = super.getResourceListing(uriInfo, context, urlPrefix);
127 resources.addAll(list.getApis());
128 list.setApis(resources);
132 private YangInstanceIdentifier getInstanceId(final Long id) {
133 final YangInstanceIdentifier instanceId;
134 synchronized (this.lock) {
135 instanceId = this.longIdToInstanceId.get(id);
140 private SchemaContext getSchemaContext(final YangInstanceIdentifier id) {
146 final Optional<DOMMountPoint> mountPoint = this.mountService.getMountPoint(id);
147 if (!mountPoint.isPresent()) {
151 final SchemaContext context = mountPoint.get().getSchemaContext();
152 if (context == null) {
158 public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module,
159 final String revision) {
160 final YangInstanceIdentifier iid = getInstanceId(id);
161 final SchemaContext context = getSchemaContext(iid);
162 final String urlPrefix = getYangMountUrl(iid);
163 if (context == null) {
167 if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) {
168 return generateDataStoreApiDoc(uriInfo, urlPrefix);
170 return super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
173 private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
174 final List<Api> apis = new LinkedList<>();
175 apis.add(createGetApi("config", "Queries the config (startup) datastore on the mounted hosted.", context));
176 apis.add(createGetApi("operational", "Queries the operational (running) datastore on the mounted hosted.",
178 apis.add(createGetApi("operations", "Queries the available operations (RPC calls) on the mounted hosted.",
181 final ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
182 declaration.setApis(apis);
187 private Api createGetApi(final String datastore, final String note, final String context) {
188 final Operation getConfig = new Operation();
189 getConfig.setMethod("GET");
190 getConfig.setNickname("GET " + datastore);
191 getConfig.setNotes(note);
193 final Api api = new Api();
194 api.setPath(getDataStorePath(datastore, context).concat(getContent(datastore)));
195 api.setOperations(Collections.singletonList(getConfig));
200 public void setMountService(final DOMMountPointService mountService) {
201 this.mountService = mountService;
205 public void onMountPointCreated(final YangInstanceIdentifier path) {
206 synchronized (this.lock) {
207 final Long idLong = this.idKey.incrementAndGet();
208 this.instanceIdToLongId.put(path, idLong);
209 this.longIdToInstanceId.put(idLong, path);
214 public void onMountPointRemoved(final YangInstanceIdentifier path) {
215 synchronized (this.lock) {
216 final Long id = this.instanceIdToLongId.remove(path);
217 this.longIdToInstanceId.remove(id);
221 public static MountPointSwagger getInstance() {
222 MountPointSwagger swagger = selfRef.get();
223 if (swagger == null) {
224 selfRef.compareAndSet(null, new MountPointSwagger());
225 swagger = selfRef.get();
231 public static MountPointSwagger getInstanceDraft18() {
232 MountPointSwagger swagger = selfRef.get();
233 if (swagger == null) {
234 selfRef.compareAndSet(null, new MountPointSwagger());
235 swagger = selfRef.get();