442958f7897bf30206d089c7c63b91660d5a36d1
[netconf.git] / restconf / restconf-openapi / src / main / java / org / opendaylight / restconf / openapi / model / OperationEntity.java
1 /*
2  * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.restconf.openapi.model;
9
10 import static java.util.Objects.requireNonNull;
11 import static javax.ws.rs.core.Response.Status.OK;
12
13 import com.fasterxml.jackson.core.JsonGenerator;
14 import java.io.IOException;
15 import java.util.List;
16 import javax.ws.rs.HttpMethod;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
20
21 /**
22  * Archetype for an Operation.
23  */
24 public abstract sealed class OperationEntity extends OpenApiEntity permits DeleteEntity, GetEntity, PatchEntity,
25         PostEntity, PutEntity {
26     protected static final String SCHEMA = "schema";
27     protected static final String SUMMARY_TEMPLATE = "%s - %s - %s - %s";
28     protected static final String RESPONSES = "responses";
29     protected static final String DESCRIPTION = "description";
30     protected static final String OBJECT = "object";
31     protected static final String CONTENT = "content";
32     protected static final String COMPONENTS_PREFIX = "#/components/schemas/";
33     protected static final String PROPERTIES = "properties";
34     protected static final String TYPE = "type";
35     protected static final String ARRAY = "array";
36     protected static final String ITEMS = "items";
37     protected static final String REF = "$ref";
38     protected static final String PARAMETERS = "parameters";
39     protected static final String SUMMARY = "summary";
40     protected static final String NAME = "name";
41     protected static final String IN = "in";
42     protected static final String REQUIRED = "required";
43     protected static final String REQUEST_BODY = "requestBody";
44
45     private final @Nullable SchemaNode schema;
46     private final @NonNull String deviceName;
47     private final @NonNull String moduleName;
48     private final @Nullable String refPath;
49     private final @Nullable List<ParameterEntity> parameters;
50
51     protected @Nullable SchemaNode schema() {
52         return schema;
53     }
54
55     protected @NonNull String deviceName() {
56         return deviceName;
57     }
58
59     protected @NonNull String moduleName() {
60         return moduleName;
61     }
62
63     protected @Nullable List<ParameterEntity> parameters() {
64         return parameters;
65     }
66
67     protected @Nullable String refPath() {
68         return refPath;
69     }
70
71     public OperationEntity(final @Nullable SchemaNode schema, final @NonNull String deviceName,
72             final @NonNull String moduleName, final @Nullable List<ParameterEntity> parameters,
73             final @Nullable String refPath) {
74         this.schema = schema;
75         this.deviceName = requireNonNull(deviceName);
76         this.moduleName = requireNonNull(moduleName);
77         this.parameters = parameters;
78         this.refPath = refPath;
79     }
80
81     @Override
82     public void generate(@NonNull JsonGenerator generator) throws IOException {
83         if (schema() == null) {
84             generateGetRoot(generator, moduleName());
85         } else {
86             generator.writeObjectFieldStart(operation());
87             generateBasics(generator);
88             generateRequestBody(generator);
89             generateResponses(generator);
90             generateTags(generator);
91             generateParams(generator);
92             generator.writeEndObject();
93         }
94     }
95
96     public void generateBasics(@NonNull JsonGenerator generator) throws IOException {
97         generator.writeStringField(DESCRIPTION, description());
98         generator.writeStringField(SUMMARY, summary());
99     }
100
101     protected @NonNull abstract String operation();
102
103     @NonNull String description() {
104         return schema == null ? "" : schema.getDescription().orElse("");
105     }
106
107     @Nullable String nodeName() {
108         return schema == null ? null : schema.getQName().getLocalName();
109     }
110
111     @NonNull abstract String summary();
112
113     abstract void generateRequestBody(@NonNull JsonGenerator generator) throws IOException;
114
115     abstract void generateResponses(@NonNull JsonGenerator generator) throws IOException;
116
117     void generateTags(final @NonNull JsonGenerator generator) throws IOException {
118         generator.writeArrayFieldStart("tags");
119         generator.writeString(deviceName + " " + moduleName);
120         generator.writeEndArray();
121     }
122
123     void generateParams(final @NonNull JsonGenerator generator) throws IOException {
124         generator.writeArrayFieldStart(PARAMETERS);
125         final var parametersList = requireNonNull(parameters());
126         if (!parametersList.isEmpty()) {
127             for (final var parameter : parametersList) {
128                 generator.writeStartObject();
129                 generator.writeStringField(NAME, parameter.name());
130                 generator.writeStringField(IN, parameter.in());
131                 generator.writeBooleanField(REQUIRED, parameter.required());
132                 generator.writeObjectFieldStart(SCHEMA);
133                 if (parameter.schema() != null) {
134                     generator.writeStringField(TYPE, parameter.schema().type());
135                 }
136                 generator.writeEndObject(); //end of schema
137                 if (parameter.description() != null) {
138                     generator.writeStringField(DESCRIPTION, parameter.description());
139                 }
140                 generator.writeEndObject(); //end of parameter
141             }
142         }
143         generator.writeEndArray(); //end of params
144     }
145
146     protected static void generateMediaTypeSchemaRef(final @NonNull JsonGenerator generator,
147             final @NonNull String mediaType, final @NonNull String ref) throws IOException {
148         generator.writeObjectFieldStart(mediaType);
149         generator.writeObjectFieldStart(SCHEMA);
150         generator.writeStringField(REF, ref);
151         generator.writeEndObject();
152         generator.writeEndObject();
153     }
154
155     void generateGetRoot(final @NonNull JsonGenerator generator, final @NonNull String resourceType)
156             throws IOException {
157         generator.writeObjectFieldStart("get");
158         if (resourceType.equals("data")) {
159             generator.writeStringField(DESCRIPTION, "Queries the config (startup) datastore on the mounted hosted.");
160         } else if (resourceType.equals("operations")) {
161             generator.writeStringField(DESCRIPTION,
162                 "Queries the available operations (RPC calls) on the mounted hosted.");
163         }
164         generator.writeObjectFieldStart(RESPONSES);
165         generator.writeObjectFieldStart(String.valueOf(OK.getStatusCode()));
166         generator.writeStringField(DESCRIPTION, "OK");
167         generator.writeEndObject(); //end of 200
168         generator.writeEndObject(); // end of responses
169         final var summary = HttpMethod.GET + " - " + deviceName() + " - datastore - " + resourceType;
170         generator.writeStringField(SUMMARY, summary);
171         generator.writeArrayFieldStart("tags");
172         generator.writeString(deviceName + " GET root");
173         generator.writeEndArray(); //end of tags
174         generator.writeEndObject(); //end of get
175     }
176 }