0f68a1cd79b9d38b726295ea7d648a8c5f62e66b
[netconf.git] / restconf / sal-rest-docgen / src / main / java / org / opendaylight / netconf / sal / rest / doc / impl / ApiDocServiceImpl.java
1 /*
2  * Copyright (c) 2014 Cisco 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.impl;
9
10 import java.util.List;
11 import java.util.Objects;
12 import java.util.Optional;
13 import java.util.stream.Collectors;
14 import javax.ws.rs.core.Response;
15 import javax.ws.rs.core.UriInfo;
16 import org.opendaylight.netconf.sal.rest.doc.api.ApiDocService;
17 import org.opendaylight.netconf.sal.rest.doc.mountpoints.MountPointSwagger;
18 import org.opendaylight.netconf.sal.rest.doc.swagger.CommonApiObject;
19 import org.opendaylight.netconf.sal.rest.doc.swagger.MountPointInstance;
20
21
22 /**
23  * This service generates swagger (See
24  * <a href="https://helloreverb.com/developers/swagger"
25  * >https://helloreverb.com/developers/swagger</a>) compliant documentation for
26  * RESTCONF APIs. The output of this is used by embedded Swagger UI.
27  *
28  * <p>
29  * NOTE: These API's need to be synchronized due to bug 1198. Thread access to
30  * the SchemaContext is not synchronized properly and thus you can end up with
31  * missing definitions without this synchronization. There are likely otherways
32  * to work around this limitation, but given that this API is a dev only tool
33  * and not dependent UI, this was the fastest work around.
34  */
35 public class ApiDocServiceImpl implements ApiDocService {
36
37     public static final int DEFAULT_PAGESIZE = 20;
38     // Query parameter
39     private static final String PAGE_NUM = "pageNum";
40
41     public enum URIType { RFC8040, DRAFT02 }
42
43     public enum OAversion { V2_0, V3_0 }
44
45     private final MountPointSwagger mountPointSwaggerDraft02;
46     private final MountPointSwagger mountPointSwaggerRFC8040;
47     private final ApiDocGeneratorDraftO2 apiDocGeneratorDraft02;
48     private final ApiDocGeneratorRFC8040 apiDocGeneratorRFC8040;
49     private final AllModulesDocGenerator allModulesDocGenerator;
50
51     public ApiDocServiceImpl(final MountPointSwaggerGeneratorDraft02 mountPointSwaggerGeneratorDraft02,
52                              final MountPointSwaggerGeneratorRFC8040 mountPointSwaggerGeneratorRFC8040,
53                              final ApiDocGeneratorDraftO2 apiDocGeneratorDraft02,
54                              final ApiDocGeneratorRFC8040 apiDocGeneratorRFC8040,
55                              final AllModulesDocGenerator allModulesDocGenerator) {
56         this.mountPointSwaggerDraft02 =
57                 Objects.requireNonNull(mountPointSwaggerGeneratorDraft02).getMountPointSwagger();
58         this.mountPointSwaggerRFC8040 =
59                 Objects.requireNonNull(mountPointSwaggerGeneratorRFC8040).getMountPointSwagger();
60         this.apiDocGeneratorDraft02 = Objects.requireNonNull(apiDocGeneratorDraft02);
61         this.apiDocGeneratorRFC8040 = Objects.requireNonNull(apiDocGeneratorRFC8040);
62         this.allModulesDocGenerator = Objects.requireNonNull(allModulesDocGenerator);
63     }
64
65     @Override
66     public synchronized Response getAllModulesDoc(final UriInfo uriInfo) {
67         final CommonApiObject allModulesDoc = allModulesDocGenerator.getAllModulesDoc(uriInfo, identifyUriType(uriInfo),
68                 identifyOpenApiVersion(uriInfo));
69         return Response.ok(allModulesDoc).build();
70     }
71
72     /**
73      * Generates Swagger compliant document listing APIs for module.
74      */
75     @Override
76     public synchronized Response getDocByModule(final String module, final String revision, final UriInfo uriInfo) {
77         final CommonApiObject doc;
78         final OAversion oaversion = identifyOpenApiVersion(uriInfo);
79         if (identifyUriType(uriInfo).equals(URIType.RFC8040)) {
80             doc = apiDocGeneratorRFC8040.getApiDeclaration(module, revision, uriInfo, URIType.RFC8040, oaversion);
81         } else {
82             doc = apiDocGeneratorDraft02.getApiDeclaration(module, revision, uriInfo, URIType.DRAFT02, oaversion);
83         }
84
85         return Response.ok(doc).build();
86     }
87
88     /**
89      * Redirects to embedded swagger ui.
90      */
91     @Override
92     public synchronized Response getApiExplorer(final UriInfo uriInfo) {
93         return Response.seeOther(uriInfo.getBaseUriBuilder().path("../explorer/index.html").build()).build();
94     }
95
96     @Override
97     public synchronized Response getListOfMounts(final UriInfo uriInfo) {
98         final MountPointSwagger mountPointSwagger;
99         if (identifyUriType(uriInfo).equals(URIType.RFC8040)) {
100             mountPointSwagger = mountPointSwaggerRFC8040;
101         } else {
102             mountPointSwagger = mountPointSwaggerDraft02;
103         }
104         final List<MountPointInstance> entity = mountPointSwagger
105                 .getInstanceIdentifiers().entrySet().stream()
106                 .map(MountPointInstance::new).collect(Collectors.toList());
107         return Response.ok(entity).build();
108     }
109
110     @Override
111     public synchronized Response getMountDocByModule(final String instanceNum, final String module,
112                                                      final String revision, final UriInfo uriInfo) {
113         final CommonApiObject api;
114         final OAversion oaversion = identifyOpenApiVersion(uriInfo);
115         if (identifyUriType(uriInfo).equals(URIType.RFC8040)) {
116             api = mountPointSwaggerRFC8040
117                     .getMountPointApi(uriInfo, Long.parseLong(instanceNum), module, revision, URIType.RFC8040,
118                             oaversion);
119         } else {
120             api = mountPointSwaggerDraft02
121                     .getMountPointApi(uriInfo, Long.parseLong(instanceNum), module, revision, URIType.DRAFT02,
122                             oaversion);
123         }
124         return Response.ok(api).build();
125     }
126
127     @Override
128     public synchronized Response getMountDoc(final String instanceNum, final UriInfo uriInfo) {
129         final CommonApiObject api;
130         final OAversion oaversion = identifyOpenApiVersion(uriInfo);
131         final String stringPageNum = uriInfo.getQueryParameters().getFirst(PAGE_NUM);
132         final Optional<Integer> pageNum = stringPageNum != null ? Optional.of(Integer.valueOf(stringPageNum))
133                 : Optional.empty();
134         if (identifyUriType(uriInfo).equals(URIType.RFC8040)) {
135             api = mountPointSwaggerRFC8040
136                     .getMountPointApi(uriInfo, Long.parseLong(instanceNum), pageNum, URIType.RFC8040,
137                             oaversion);
138         } else {
139             api = mountPointSwaggerDraft02
140                     .getMountPointApi(uriInfo, Long.parseLong(instanceNum), pageNum, URIType.DRAFT02,
141                             oaversion);
142         }
143         return Response.ok(api).build();
144     }
145
146     private static URIType identifyUriType(final UriInfo uriInfo) {
147         if (uriInfo.getBaseUri().toString().contains("/18/")) {
148             return URIType.RFC8040;
149         }
150         return URIType.DRAFT02;
151     }
152
153     private static OAversion identifyOpenApiVersion(final UriInfo uriInfo) {
154         if (uriInfo.getBaseUri().toString().contains("/swagger2/")) {
155             return OAversion.V2_0;
156         }
157         return OAversion.V3_0;
158     }
159 }