io.helidon.openapi.CustomConstructor Maven / Gradle / Ivy
/*
* Copyright (c) 2019, 2021 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.helidon.openapi;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.microprofile.openapi.models.PathItem;
import org.eclipse.microprofile.openapi.models.Paths;
import org.eclipse.microprofile.openapi.models.callbacks.Callback;
import org.eclipse.microprofile.openapi.models.media.Content;
import org.eclipse.microprofile.openapi.models.media.MediaType;
import org.eclipse.microprofile.openapi.models.responses.APIResponse;
import org.eclipse.microprofile.openapi.models.responses.APIResponses;
import org.eclipse.microprofile.openapi.models.security.Scopes;
import org.eclipse.microprofile.openapi.models.security.SecurityRequirement;
import org.eclipse.microprofile.openapi.models.servers.ServerVariable;
import org.eclipse.microprofile.openapi.models.servers.ServerVariables;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.Mark;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
/**
* Specialized SnakeYAML constructor for modifying {@code Node} objects for OpenAPI types that extend {@code Map} to adjust the
* type of the child nodes of such nodes.
*
* Several MicroProfile OpenAPI interfaces extend {@code Map}. For example, {@code Paths} extends {@code Map
* } and {@code SecurityRequirement} extends {@code Map>}. When SnakeYAML builds the node
* corresponding to one of these types, it correctly creates each child node as a {@code MappingNode} but it assigns those
* child nodes a type of {@code Object} instead of the mapped type -- {@code PathItem} in the example above.
*
*
* This class customizes the preparation of the node tree in these situations by setting the types for the child nodes explicitly
* to the corresponding child type. In OpenAPI 1.1.2 there are two situations, depending on whether the mapped-to type is a
* {@code List} or not.
*
*
* The MicroProfile OpenAPI 2.0 versions of the interfaces no longer use this construct of an interface extending {@code Map}, so
* ideally we can remove this workaround when we adopt 2.0.
*
*/
final class CustomConstructor extends Constructor {
// maps OpenAPI interfaces which extend Map, type> to the mapped-to type where that mapped-to type is NOT List
private static final Map, Class>> CHILD_MAP_TYPES = new HashMap<>();
// maps OpenAPI interfaces which extend Map, List> to the type that appears in the list
private static final Map, Class>> CHILD_MAP_OF_LIST_TYPES = new HashMap<>();
private static final Logger LOGGER = Logger.getLogger(CustomConstructor.class.getName());
static {
CHILD_MAP_TYPES.put(Paths.class, PathItem.class);
CHILD_MAP_TYPES.put(Callback.class, PathItem.class);
CHILD_MAP_TYPES.put(Content.class, MediaType.class);
CHILD_MAP_TYPES.put(APIResponses.class, APIResponse.class);
CHILD_MAP_TYPES.put(ServerVariables.class, ServerVariable.class);
CHILD_MAP_TYPES.put(Scopes.class, String.class);
CHILD_MAP_OF_LIST_TYPES.put(SecurityRequirement.class, String.class);
}
CustomConstructor(TypeDescription td) {
super(td);
}
@Override
protected void constructMapping2ndStep(MappingNode node, Map