Merge "Remove deprecated registerDataChangeListener method"
[netconf.git] / restconf / sal-rest-docgen / src / main / java / org / opendaylight / netconf / sal / rest / doc / mountpoints / MountPointSwagger.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.sal.rest.doc.mountpoints;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Map;
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.netconf.sal.rest.doc.impl.BaseYangSwaggerGenerator;
27 import org.opendaylight.netconf.sal.rest.doc.swagger.Api;
28 import org.opendaylight.netconf.sal.rest.doc.swagger.ApiDeclaration;
29 import org.opendaylight.netconf.sal.rest.doc.swagger.Operation;
30 import org.opendaylight.netconf.sal.rest.doc.swagger.Resource;
31 import org.opendaylight.netconf.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;
38
39 public class MountPointSwagger extends BaseYangSwaggerGenerator implements MountProvisionListener {
40
41     private static final String DATASTORES_REVISION = "-";
42     private static final String DATASTORES_LABEL = "Datastores";
43     private static final AtomicReference<MountPointSwagger> SELF_REF = new AtomicReference<>();
44
45     private DOMMountPointService mountService;
46     private final Map<YangInstanceIdentifier, Long> instanceIdToLongId =
47             new TreeMap<>((o1, o2) -> o1.toString().compareToIgnoreCase(o2.toString()));
48     private final Map<Long, YangInstanceIdentifier> longIdToInstanceId = new HashMap<>();
49
50     private final Object lock = new Object();
51
52     private final AtomicLong idKey = new AtomicLong(0);
53     private SchemaService globalSchema;
54
55     public Map<String, Long> getInstanceIdentifiers() {
56         Preconditions.checkState(globalSchema != null);
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());
63             }
64         }
65         return urlToId;
66     }
67
68     public void setGlobalSchema(final SchemaService globalSchema) {
69         this.globalSchema = globalSchema;
70     }
71
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) {
76                 return mod.getName();
77             }
78         }
79         return null;
80     }
81
82     private String generateUrlPrefixFromInstanceID(final YangInstanceIdentifier key, final String moduleName) {
83         final StringBuilder builder = new StringBuilder();
84         builder.append("/");
85         if (moduleName != null) {
86             builder.append(moduleName).append(':');
87         }
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()) {
93                     if (isNewDraft()) {
94                         builder.deleteCharAt(builder.length() - 1).append("=").append(entry.getValue()).append('/');
95                     } else {
96                         builder.append(entry.getValue()).append('/');
97                     }
98                 }
99             } else {
100                 builder.append(name).append('/');
101             }
102         }
103         return builder.toString();
104     }
105
106     private String getYangMountUrl(final YangInstanceIdentifier key) {
107         Preconditions.checkState(globalSchema != null);
108         final String modName = findModuleName(key, this.globalSchema.getGlobalContext());
109         return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount";
110     }
111
112     public ResourceList getResourceList(final UriInfo uriInfo, final Long id) {
113         final YangInstanceIdentifier iid = getInstanceId(id);
114         if (iid == null) {
115             return null; // indicating not found.
116         }
117         final SchemaContext context = getSchemaContext(iid);
118         if (context == null) {
119             return createResourceList();
120         }
121         final List<Resource> resources = new LinkedList<>();
122         final Resource dataStores = new Resource();
123         dataStores.setDescription("Provides methods for accessing the data stores.");
124         dataStores.setPath(generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
125         resources.add(dataStores);
126         final String urlPrefix = getYangMountUrl(iid);
127         final ResourceList list = super.getResourceListing(uriInfo, context, urlPrefix);
128         resources.addAll(list.getApis());
129         list.setApis(resources);
130         return list;
131     }
132
133     private YangInstanceIdentifier getInstanceId(final Long id) {
134         final YangInstanceIdentifier instanceId;
135         synchronized (this.lock) {
136             instanceId = this.longIdToInstanceId.get(id);
137         }
138         return instanceId;
139     }
140
141     private SchemaContext getSchemaContext(final YangInstanceIdentifier id) {
142
143         if (id == null) {
144             return null;
145         }
146
147         Preconditions.checkState(mountService != null);
148         final Optional<DOMMountPoint> mountPoint = this.mountService.getMountPoint(id);
149         if (!mountPoint.isPresent()) {
150             return null;
151         }
152
153         final SchemaContext context = mountPoint.get().getSchemaContext();
154         if (context == null) {
155             return null;
156         }
157         return context;
158     }
159
160     public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module,
161             final String revision) {
162         final YangInstanceIdentifier iid = getInstanceId(id);
163         final SchemaContext context = getSchemaContext(iid);
164         final String urlPrefix = getYangMountUrl(iid);
165         if (context == null) {
166             return null;
167         }
168
169         if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) {
170             return generateDataStoreApiDoc(uriInfo, urlPrefix);
171         }
172         return super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
173     }
174
175     private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
176         final List<Api> apis = new LinkedList<>();
177         apis.add(createGetApi("config", "Queries the config (startup) datastore on the mounted hosted.", context));
178         apis.add(createGetApi("operational", "Queries the operational (running) datastore on the mounted hosted.",
179                 context));
180         apis.add(createGetApi("operations", "Queries the available operations (RPC calls) on the mounted hosted.",
181                 context));
182
183         final ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
184         declaration.setApis(apis);
185         return declaration;
186
187     }
188
189     private Api createGetApi(final String datastore, final String note, final String context) {
190         final Operation getConfig = new Operation();
191         getConfig.setMethod("GET");
192         getConfig.setNickname("GET " + datastore);
193         getConfig.setNotes(note);
194
195         final Api api = new Api();
196         api.setPath(getDataStorePath(datastore, context).concat(getContent(datastore)));
197         api.setOperations(Collections.singletonList(getConfig));
198
199         return api;
200     }
201
202     public void setMountService(final DOMMountPointService mountService) {
203         this.mountService = mountService;
204     }
205
206     @Override
207     public void onMountPointCreated(final YangInstanceIdentifier path) {
208         synchronized (this.lock) {
209             final Long idLong = this.idKey.incrementAndGet();
210             this.instanceIdToLongId.put(path, idLong);
211             this.longIdToInstanceId.put(idLong, path);
212         }
213     }
214
215     @Override
216     public void onMountPointRemoved(final YangInstanceIdentifier path) {
217         synchronized (this.lock) {
218             final Long id = this.instanceIdToLongId.remove(path);
219             this.longIdToInstanceId.remove(id);
220         }
221     }
222
223     public static MountPointSwagger getInstance() {
224         MountPointSwagger swagger = SELF_REF.get();
225         if (swagger == null) {
226             SELF_REF.compareAndSet(null, new MountPointSwagger());
227             swagger = SELF_REF.get();
228         }
229
230         swagger.setDraft(false);
231         return swagger;
232     }
233
234     public static MountPointSwagger getInstanceDraft18() {
235         MountPointSwagger swagger = SELF_REF.get();
236         if (swagger == null) {
237             SELF_REF.compareAndSet(null, new MountPointSwagger());
238             swagger = SELF_REF.get();
239         }
240
241         swagger.setDraft(true);
242         return swagger;
243     }
244 }