OpenAPI: Delete no-op methods
[netconf.git] / restconf / restconf-openapi / src / main / java / org / opendaylight / restconf / openapi / model / SchemaEntity.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 java.util.Objects.requireNonNullElse;
12 import static org.opendaylight.restconf.openapi.model.PropertyEntity.isSchemaNodeMandatory;
13
14 import com.fasterxml.jackson.core.JsonGenerator;
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.opendaylight.restconf.openapi.impl.DefinitionNames;
22 import org.opendaylight.restconf.openapi.impl.SchemasStream;
23 import org.opendaylight.yangtools.yang.model.api.ContainerLike;
24 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
26 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.InputSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.OutputSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
30 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
31
32 /**
33  * Archetype for a Schema.
34  */
35 public final class SchemaEntity extends OpenApiEntity {
36     private final @NonNull SchemaNode value;
37     private final @NonNull String title;
38     private final @NonNull String discriminator;
39     private final @NonNull String type;
40     private final @NonNull SchemaInferenceStack stack;
41     private final boolean isParentConfig;
42     private final SchemasStream.EntityType entityType;
43     private final @NonNull String parentName;
44     private final @NonNull DefinitionNames definitionNames;
45
46     public SchemaEntity(final @NonNull SchemaNode value, final @NonNull String title, final String discriminator,
47             @NonNull final String type, @NonNull final SchemaInferenceStack context, final String parentName,
48             final boolean isParentConfig, @NonNull final DefinitionNames definitionNames,
49             final SchemasStream.EntityType entityType) {
50         this.value = requireNonNull(value);
51         this.title = requireNonNull(title);
52         this.type = requireNonNull(type);
53         this.stack = requireNonNull(context.copy());
54         this.parentName = requireNonNull(parentName);
55         this.isParentConfig = isParentConfig;
56         this.definitionNames = definitionNames;
57         this.entityType = entityType;
58         this.discriminator = requireNonNullElse(discriminator, "");
59     }
60
61     @Override
62     public void generate(final @NonNull JsonGenerator generator) throws IOException {
63         generator.writeObjectFieldStart(title() + discriminator);
64         generator.writeStringField("title", title());
65         generator.writeStringField("type", type());
66         final var description = description();
67         if (description != null) {
68             generator.writeStringField("description", description);
69         }
70         generateProperties(generator);
71         generateXml(generator);
72         generator.writeEndObject();
73     }
74
75     private @NonNull String title() {
76         return title;
77     }
78
79     private @NonNull String type() {
80         return type;
81     }
82
83     private @Nullable String description() {
84         // FIXME: Ensure the method returns null if the description is not available.
85         return value.getDescription()
86             .orElse(value instanceof InputSchemaNode || value instanceof OutputSchemaNode ? null : "");
87     }
88
89     private void generateRequired(final @NonNull JsonGenerator generator, final List<String> required)
90             throws IOException {
91         if (!required.isEmpty()) {
92             generator.writeArrayFieldStart("required");
93             for (final var req : required) {
94                 generator.writeString(req);
95             }
96             generator.writeEndArray();
97         }
98     }
99
100     private void generateProperties(final @NonNull JsonGenerator generator) throws IOException {
101         final var required = new ArrayList<String>();
102         generator.writeObjectFieldStart("properties");
103         stack.enterSchemaTree(value.getQName());
104         switch (entityType) {
105             case RPC:
106                 for (final var childNode : ((ContainerLike) value).getChildNodes()) {
107                     new PropertyEntity(childNode, generator, stack, required, parentName, isParentConfig,
108                         definitionNames);
109                 }
110                 break;
111             default:
112                 final var childNodes = new HashMap<String, DataSchemaNode>();
113                 for (final var childNode : ((DataNodeContainer) value).getChildNodes()) {
114                     childNodes.put(childNode.getQName().getLocalName(), childNode);
115                 }
116                 for (final var childNode : childNodes.values()) {
117                     if (shouldBeAddedAsProperty(childNode)) {
118                         new PropertyEntity(childNode, generator, stack, required, parentName + "_"
119                             + value.getQName().getLocalName(), ((DataSchemaNode) value).isConfiguration(),
120                             definitionNames);
121                     }
122                 }
123         }
124         stack.exit();
125         generator.writeEndObject();
126         generateRequired(generator, required);
127     }
128
129     private boolean shouldBeAddedAsProperty(final DataSchemaNode childNode) {
130         if (childNode instanceof ContainerSchemaNode) {
131             return childNode.isConfiguration() || isSchemaNodeMandatory(childNode)
132                 || !((DataSchemaNode) value).isConfiguration();
133         }
134         return childNode.isConfiguration() || !((DataSchemaNode) value).isConfiguration();
135     }
136
137     private void generateXml(final @NonNull JsonGenerator generator) throws IOException {
138         generator.writeObjectFieldStart("xml");
139         generator.writeStringField("name", value.getQName().getLocalName());
140         generator.writeStringField("namespace", value.getQName().getNamespace().toString());
141         generator.writeEndObject();
142     }
143 }