7e8707110fb757e9fae69fb2e02837d34d5b22cf
[controller.git] / opendaylight / md-sal / sal-rest-docgen / src / main / java / org / opendaylight / controller / 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.controller.sal.rest.doc.mountpoints;
9
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;
15 import java.util.Map;
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.sal.core.api.model.SchemaService;
22 import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
23 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
24 import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
25 import org.opendaylight.controller.sal.rest.doc.impl.BaseYangSwaggerGenerator;
26 import org.opendaylight.controller.sal.rest.doc.swagger.Api;
27 import org.opendaylight.controller.sal.rest.doc.swagger.ApiDeclaration;
28 import org.opendaylight.controller.sal.rest.doc.swagger.Operation;
29 import org.opendaylight.controller.sal.rest.doc.swagger.Resource;
30 import org.opendaylight.controller.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;
37
38 public class MountPointSwagger extends BaseYangSwaggerGenerator implements MountProvisionListener {
39
40     private static final String DATASTORES_REVISION = "-";
41     private static final String DATASTORES_LABEL = "Datastores";
42
43     private MountProvisionService mountService;
44     private final Map<YangInstanceIdentifier, Long> instanceIdToLongId = new TreeMap<>(
45             new Comparator<YangInstanceIdentifier>() {
46                 @Override
47                 public int compare(final YangInstanceIdentifier o1, final YangInstanceIdentifier o2) {
48                     return o1.toString().compareToIgnoreCase(o2.toString());
49                 }
50             });
51     private final Map<Long, YangInstanceIdentifier> longIdToInstanceId = new HashMap<>();
52     private final Object lock = new Object();
53
54     private final AtomicLong idKey = new AtomicLong(0);
55
56     private static AtomicReference<MountPointSwagger> selfRef = new AtomicReference<>();
57     private SchemaService globalSchema;
58
59     public Map<String, Long> getInstanceIdentifiers() {
60         Map<String, Long> urlToId = new HashMap<>();
61         synchronized (lock) {
62             SchemaContext context = globalSchema.getGlobalContext();
63             for (Entry<YangInstanceIdentifier, Long> entry : instanceIdToLongId.entrySet()) {
64                 String modName = findModuleName(entry.getKey(), context);
65                 urlToId.put(generateUrlPrefixFromInstanceID(entry.getKey(), modName),
66                         entry.getValue());
67             }
68         }
69         return urlToId;
70     }
71
72     public void setGlobalSchema(final SchemaService globalSchema) {
73         this.globalSchema = globalSchema;
74     }
75
76     private String findModuleName(final YangInstanceIdentifier id, final SchemaContext context) {
77         PathArgument rootQName = id.getPathArguments().iterator().next();
78         for (Module mod : context.getModules()) {
79             if (mod.getDataChildByName(rootQName.getNodeType()) != null) {
80                 return mod.getName();
81             }
82         }
83         return null;
84     }
85
86     private String generateUrlPrefixFromInstanceID(final YangInstanceIdentifier key, final String moduleName) {
87         StringBuilder builder = new StringBuilder();
88         if (moduleName != null) {
89             builder.append(moduleName);
90             builder.append(':');
91         }
92         boolean first = true;
93         for (PathArgument arg : key.getPathArguments()) {
94
95             String name = arg.getNodeType().getLocalName();
96             if (first) {
97                 first = false;
98             } else {
99                 builder.append('/');
100             }
101             builder.append(name);
102             if (arg instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) {
103                 NodeIdentifierWithPredicates nodeId = (NodeIdentifierWithPredicates) arg;
104                 for (Entry<QName, Object> entry : nodeId.getKeyValues().entrySet()) {
105                     builder.append('/').append(entry.getValue());
106                 }
107             }
108         }
109
110         return builder.append('/').toString();
111     }
112
113     private String getYangMountUrl(final YangInstanceIdentifier key) {
114         String modName = findModuleName(key, globalSchema.getGlobalContext());
115         return generateUrlPrefixFromInstanceID(key, modName) + "yang-ext:mount/";
116     }
117
118     public ResourceList getResourceList(final UriInfo uriInfo, final Long id) {
119         YangInstanceIdentifier iid = getInstanceId(id);
120         if (iid == null) {
121             return null; // indicating not found.
122         }
123         SchemaContext context = getSchemaContext(iid);
124         String urlPrefix = getYangMountUrl(iid);
125         if (context == null) {
126             return createResourceList();
127         }
128         List<Resource> resources = new LinkedList<>();
129         Resource dataStores = new Resource();
130         dataStores.setDescription("Provides methods for accessing the data stores.");
131         dataStores.setPath(generatePath(uriInfo, DATASTORES_LABEL, DATASTORES_REVISION));
132         resources.add(dataStores);
133         ResourceList list = super.getResourceListing(uriInfo, context, urlPrefix);
134         resources.addAll(list.getApis());
135         list.setApis(resources);
136         return list;
137     }
138
139     private YangInstanceIdentifier getInstanceId(final Long id) {
140         YangInstanceIdentifier instanceId;
141         synchronized (lock) {
142             instanceId = longIdToInstanceId.get(id);
143         }
144         return instanceId;
145     }
146
147     private SchemaContext getSchemaContext(final YangInstanceIdentifier id) {
148
149         if (id == null) {
150             return null;
151         }
152
153         MountProvisionInstance mountPoint = mountService.getMountPoint(id);
154         if (mountPoint == null) {
155             return null;
156         }
157
158         SchemaContext context = mountPoint.getSchemaContext();
159         if (context == null) {
160             return null;
161         }
162         return context;
163     }
164
165     public ApiDeclaration getMountPointApi(final UriInfo uriInfo, final Long id, final String module, final String revision) {
166         YangInstanceIdentifier iid = getInstanceId(id);
167         SchemaContext context = getSchemaContext(iid);
168         String urlPrefix = getYangMountUrl(iid);
169         if (context == null) {
170             return null;
171         }
172
173         if (DATASTORES_LABEL.equals(module) && DATASTORES_REVISION.equals(revision)) {
174             return generateDataStoreApiDoc(uriInfo, urlPrefix);
175         }
176         return super.getApiDeclaration(module, revision, uriInfo, context, urlPrefix);
177     }
178
179     private ApiDeclaration generateDataStoreApiDoc(final UriInfo uriInfo, final String context) {
180
181         ApiDeclaration declaration = super.createApiDeclaration(createBasePathFromUriInfo(uriInfo));
182         List<Api> apis = new LinkedList<>();
183         apis.add(createGetApi("config",
184                 "Queries the config (startup) datastore on the mounted hosted.", context));
185         apis.add(createGetApi("operational",
186                 "Queries the operational (running) datastore on the mounted hosted.", context));
187         apis.add(createGetApi("operations",
188                 "Queries the available operations (RPC calls) on the mounted hosted.", context));
189         declaration.setApis(apis);
190         return declaration;
191
192     }
193
194     private Api createGetApi(final String datastore, final String note, final String context) {
195         Operation getConfig = new Operation();
196         getConfig.setMethod("GET");
197         getConfig.setNickname("GET " + datastore);
198         getConfig.setNotes(note);
199
200         Api api = new Api();
201         api.setPath(getDataStorePath("/" + datastore + "/", context));
202         api.setOperations(Collections.singletonList(getConfig));
203
204         return api;
205     }
206
207     public void setMountService(final MountProvisionService mountService) {
208         this.mountService = mountService;
209     }
210
211     @Override
212     public void onMountPointCreated(final YangInstanceIdentifier path) {
213         synchronized (lock) {
214             Long idLong = idKey.incrementAndGet();
215             instanceIdToLongId.put(path, idLong);
216             longIdToInstanceId.put(idLong, path);
217         }
218     }
219
220     @Override
221     public void onMountPointRemoved(final YangInstanceIdentifier path) {
222         synchronized (lock) {
223             Long id = instanceIdToLongId.remove(path);
224             longIdToInstanceId.remove(id);
225         }
226     }
227
228     public static MountPointSwagger getInstance() {
229         MountPointSwagger swagger = selfRef.get();
230         if (swagger == null) {
231             selfRef.compareAndSet(null, new MountPointSwagger());
232             swagger = selfRef.get();
233         }
234         return swagger;
235     }
236
237 }