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.SchemaNode;
28 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
31 * Archetype for a Schema.
33 public final class SchemaEntity extends OpenApiEntity {
34 private final @NonNull SchemaNode value;
35 private final @NonNull String title;
36 private final @NonNull String discriminator;
37 private final @NonNull String type;
38 private final @NonNull SchemaInferenceStack stack;
39 private final boolean isParentConfig;
40 private final SchemasStream.EntityType entityType;
41 private final @NonNull String parentName;
42 private final @NonNull DefinitionNames definitionNames;
44 public SchemaEntity(final @NonNull SchemaNode value, final @NonNull String title, final String discriminator,
45 @NonNull final String type, @NonNull final SchemaInferenceStack context, final String parentName,
46 final boolean isParentConfig, @NonNull final DefinitionNames definitionNames,
47 final SchemasStream.EntityType entityType) {
48 this.value = requireNonNull(value);
49 this.title = requireNonNull(title);
50 this.type = requireNonNull(type);
51 this.stack = requireNonNull(context.copy());
52 this.parentName = requireNonNull(parentName);
53 this.isParentConfig = isParentConfig;
54 this.definitionNames = definitionNames;
55 this.entityType = entityType;
56 this.discriminator = requireNonNullElse(discriminator, "");
60 public void generate(final @NonNull JsonGenerator generator) throws IOException {
61 generator.writeObjectFieldStart(title() + discriminator);
62 generator.writeStringField("title", title());
63 generator.writeStringField("type", type());
64 final var description = description();
65 if (description != null) {
66 generator.writeStringField("description", description);
68 generateProperties(generator);
69 generateXml(generator);
70 generator.writeEndObject();
73 private @NonNull String title() {
77 private @NonNull String type() {
81 private @Nullable String description() {
82 return value.getDescription().orElse(null);
85 private void generateRequired(final @NonNull JsonGenerator generator, final List<String> required)
87 if (!required.isEmpty()) {
88 generator.writeArrayFieldStart("required");
89 for (final var req : required) {
90 generator.writeString(req);
92 generator.writeEndArray();
96 private void generateProperties(final @NonNull JsonGenerator generator) throws IOException {
97 final var required = new ArrayList<String>();
98 generator.writeObjectFieldStart("properties");
99 stack.enterSchemaTree(value.getQName());
100 switch (entityType) {
102 for (final var childNode : ((ContainerLike) value).getChildNodes()) {
103 new PropertyEntity(childNode, generator, stack, required, parentName, isParentConfig,
108 final var childNodes = new HashMap<String, DataSchemaNode>();
109 for (final var childNode : ((DataNodeContainer) value).getChildNodes()) {
110 childNodes.put(childNode.getQName().getLocalName(), childNode);
112 for (final var childNode : childNodes.values()) {
113 if (shouldBeAddedAsProperty(childNode)) {
114 new PropertyEntity(childNode, generator, stack, required, parentName + "_"
115 + value.getQName().getLocalName(), ((DataSchemaNode) value).isConfiguration(),
121 generator.writeEndObject();
122 generateRequired(generator, required);
125 private boolean shouldBeAddedAsProperty(final DataSchemaNode childNode) {
126 if (childNode instanceof ContainerSchemaNode) {
127 return childNode.isConfiguration() || isSchemaNodeMandatory(childNode)
128 || !((DataSchemaNode) value).isConfiguration();
130 return childNode.isConfiguration() || !((DataSchemaNode) value).isConfiguration();
133 private void generateXml(final @NonNull JsonGenerator generator) throws IOException {
134 generator.writeObjectFieldStart("xml");
135 generator.writeStringField("name", value.getQName().getLocalName());
136 generator.writeStringField("namespace", value.getQName().getNamespace().toString());
137 generator.writeEndObject();