2 * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.restconf.openapi.model;
10 import static java.util.Objects.requireNonNull;
11 import static java.util.Objects.requireNonNullElse;
12 import static org.opendaylight.restconf.openapi.model.PropertyEntity.isSchemaNodeMandatory;
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;
33 * Archetype for a Schema.
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;
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, "");
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);
70 final var reference = reference();
71 if (reference != null) {
72 generator.writeStringField("$ref", reference);
74 generateEnum(generator);
75 generateDiscriminator(generator);
76 generateExamples(generator);
77 generateExternalDocs(generator);
78 generateProperties(generator);
79 generateXml(generator);
80 generator.writeEndObject();
83 private @NonNull String title() {
87 private @NonNull String type() {
91 private @Nullable String description() {
92 // FIXME: Ensure the method returns null if the description is not available.
93 return value.getDescription()
94 .orElse(value instanceof InputSchemaNode || value instanceof OutputSchemaNode ? null : "");
97 private @Nullable String reference() {
101 private void generateEnum(final @NonNull JsonGenerator generator) throws IOException {
105 private void generateRequired(final @NonNull JsonGenerator generator, final List<String> required)
107 if (!required.isEmpty()) {
108 generator.writeArrayFieldStart("required");
109 for (final var req : required) {
110 generator.writeString(req);
112 generator.writeEndArray();
116 private void generateDiscriminator(final @NonNull JsonGenerator generator) throws IOException {
120 private void generateExamples(final @NonNull JsonGenerator generator) throws IOException {
124 private void generateExternalDocs(final @NonNull JsonGenerator generator) throws IOException {
128 private void generateProperties(final @NonNull JsonGenerator generator) throws IOException {
129 final var required = new ArrayList<String>();
130 generator.writeObjectFieldStart("properties");
131 stack.enterSchemaTree(value.getQName());
132 switch (entityType) {
134 for (final var childNode : ((ContainerLike) value).getChildNodes()) {
135 new PropertyEntity(childNode, generator, stack, required, parentName, isParentConfig,
140 final var childNodes = new HashMap<String, DataSchemaNode>();
141 for (final var childNode : ((DataNodeContainer) value).getChildNodes()) {
142 childNodes.put(childNode.getQName().getLocalName(), childNode);
144 for (final var childNode : childNodes.values()) {
145 if (shouldBeAddedAsProperty(childNode)) {
146 new PropertyEntity(childNode, generator, stack, required, parentName + "_"
147 + value.getQName().getLocalName(), ((DataSchemaNode) value).isConfiguration(),
153 generator.writeEndObject();
154 generateRequired(generator, required);
157 private boolean shouldBeAddedAsProperty(final DataSchemaNode childNode) {
158 if (childNode instanceof ContainerSchemaNode) {
159 return childNode.isConfiguration() || isSchemaNodeMandatory(childNode)
160 || !((DataSchemaNode) value).isConfiguration();
162 return childNode.isConfiguration() || !((DataSchemaNode) value).isConfiguration();
165 private void generateXml(final @NonNull JsonGenerator generator) throws IOException {
166 generator.writeObjectFieldStart("xml");
167 generator.writeStringField("name", value.getQName().getLocalName());
168 generator.writeStringField("namespace", value.getQName().getNamespace().toString());
169 generator.writeEndObject();