Search in sources :

Example 26 with DataNodeContainer

use of org.opendaylight.yangtools.yang.model.api.DataNodeContainer in project netconf by opendaylight.

the class RestconfDocumentedExceptionMapper method toXMLResponseBody.

private static Object toXMLResponseBody(final NormalizedNodeContext errorsNode, final DataNodeContainer errorsSchemaNode) {
    final InstanceIdentifierContext<?> pathContext = errorsNode.getInstanceIdentifierContext();
    final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    final XMLStreamWriter xmlWriter;
    try {
        xmlWriter = XML_FACTORY.createXMLStreamWriter(outStream, StandardCharsets.UTF_8.name());
    } catch (final XMLStreamException | FactoryConfigurationError e) {
        throw new IllegalStateException(e);
    }
    NormalizedNode data = errorsNode.getData();
    SchemaPath schemaPath;
    boolean isDataRoot = false;
    if (pathContext.getSchemaNode() instanceof SchemaContext) {
        isDataRoot = true;
        schemaPath = SchemaPath.ROOT;
    } else {
        final List<QName> qNames = pathContext.getInstanceIdentifier().getPathArguments().stream().filter(arg -> !(arg instanceof NodeIdentifierWithPredicates)).filter(arg -> !(arg instanceof AugmentationIdentifier)).map(PathArgument::getNodeType).collect(Collectors.toList());
        schemaPath = SchemaPath.of(Absolute.of(qNames)).getParent();
    }
    final NormalizedNodeStreamWriter xmlStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, pathContext.getSchemaContext(), schemaPath);
    // We create a delegating writer to special-case error-info as error-info is defined as an empty
    // container in the restconf yang schema but we create a leaf node so we can output it. The delegate
    // stream writer validates the node type against the schema and thus will expect a LeafSchemaNode but
    // the schema has a ContainerSchemaNode so, to avoid an error, we override the leafNode behavior
    // for error-info.
    final NormalizedNodeStreamWriter streamWriter = new ForwardingNormalizedNodeStreamWriter() {

        private boolean inOurLeaf;

        @Override
        protected NormalizedNodeStreamWriter delegate() {
            return xmlStreamWriter;
        }

        @Override
        public void startLeafNode(final NodeIdentifier name) throws IOException {
            if (name.getNodeType().equals(RestConfModule.ERROR_INFO_QNAME)) {
                String ns = RestConfModule.ERROR_INFO_QNAME.getNamespace().toString();
                try {
                    xmlWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, RestConfModule.ERROR_INFO_QNAME.getLocalName(), ns);
                } catch (XMLStreamException e) {
                    throw new IOException("Error writing error-info", e);
                }
                inOurLeaf = true;
            } else {
                super.startLeafNode(name);
            }
        }

        @Override
        public void scalarValue(final Object value) throws IOException {
            if (inOurLeaf) {
                try {
                    xmlWriter.writeCharacters(value.toString());
                } catch (XMLStreamException e) {
                    throw new IOException("Error writing error-info", e);
                }
            } else {
                super.scalarValue(value);
            }
        }

        @Override
        public void endNode() throws IOException {
            if (inOurLeaf) {
                try {
                    xmlWriter.writeEndElement();
                } catch (XMLStreamException e) {
                    throw new IOException("Error writing error-info", e);
                }
                inOurLeaf = false;
            } else {
                super.endNode();
            }
        }
    };
    final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(streamWriter);
    try {
        if (isDataRoot) {
            writeRootElement(xmlWriter, nnWriter, (ContainerNode) data);
        } else {
            if (data instanceof MapEntryNode) {
                // Restconf allows returning one list item. We need to wrap it
                // in map node in order to serialize it properly
                data = ImmutableNodes.mapNodeBuilder(data.getIdentifier().getNodeType()).addChild((MapEntryNode) data).build();
            }
            nnWriter.write(data);
            nnWriter.flush();
        }
    } catch (final IOException e) {
        LOG.warn("Error writing error response body.", e);
    }
    return outStream.toString(StandardCharsets.UTF_8);
}
Also used : JSONNormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter) JSONCodecFactorySupplier(org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier) Provider(javax.ws.rs.ext.Provider) NodeIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier) ForwardingNormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter) SchemaContext(org.opendaylight.yangtools.yang.model.api.SchemaContext) ExceptionMapper(javax.ws.rs.ext.ExceptionMapper) LoggerFactory(org.slf4j.LoggerFactory) XMLNamespace(org.opendaylight.yangtools.yang.common.XMLNamespace) Absolute(org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) ERRORS_CONTAINER_QNAME(org.opendaylight.netconf.sal.rest.api.Draft02.RestConfModule.ERRORS_CONTAINER_QNAME) MediaType(javax.ws.rs.core.MediaType) NormalizedNodeWriter(org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter) XMLStreamException(javax.xml.stream.XMLStreamException) YangInstanceIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier) XMLStreamWriter(javax.xml.stream.XMLStreamWriter) ContainerNode(org.opendaylight.yangtools.yang.data.api.schema.ContainerNode) CollectionNodeBuilder(org.opendaylight.yangtools.yang.data.api.schema.builder.CollectionNodeBuilder) Context(javax.ws.rs.core.Context) ListSchemaNode(org.opendaylight.yangtools.yang.model.api.ListSchemaNode) ContainerSchemaNode(org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode) DataContainerChild(org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) Preconditions.checkState(com.google.common.base.Preconditions.checkState) ErrorTags(org.opendaylight.restconf.common.ErrorTags) XMLStreamNormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter) List(java.util.List) HttpHeaders(javax.ws.rs.core.HttpHeaders) Response(javax.ws.rs.core.Response) PathArgument(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument) ImmutableNodes(org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes) MapEntryNode(org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode) Iterables(com.google.common.collect.Iterables) SchemaPath(org.opendaylight.yangtools.yang.model.api.SchemaPath) ByteArrayOutputStream(java.io.ByteArrayOutputStream) InstanceIdentifierContext(org.opendaylight.restconf.common.context.InstanceIdentifierContext) ArrayList(java.util.ArrayList) RestConfModule(org.opendaylight.netconf.sal.rest.api.Draft02.RestConfModule) JsonWriterFactory(org.opendaylight.yangtools.yang.data.codec.gson.JsonWriterFactory) Objects.requireNonNull(java.util.Objects.requireNonNull) OutputStreamWriter(java.io.OutputStreamWriter) SystemMapNode(org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode) XMLConstants(javax.xml.XMLConstants) JsonWriter(com.google.gson.stream.JsonWriter) Status(javax.ws.rs.core.Response.Status) SchemaAwareBuilders(org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders) Logger(org.slf4j.Logger) DataContainerNodeBuilder(org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder) IOException(java.io.IOException) NodeIdentifierWithPredicates(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates) RestconfError(org.opendaylight.restconf.common.errors.RestconfError) QName(org.opendaylight.yangtools.yang.common.QName) FactoryConfigurationError(javax.xml.stream.FactoryConfigurationError) XMLOutputFactory(javax.xml.stream.XMLOutputFactory) DataNodeContainer(org.opendaylight.yangtools.yang.model.api.DataNodeContainer) NormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter) DataSchemaNode(org.opendaylight.yangtools.yang.model.api.DataSchemaNode) ControllerContext(org.opendaylight.netconf.sal.restconf.impl.ControllerContext) RestconfDocumentedException(org.opendaylight.restconf.common.errors.RestconfDocumentedException) AugmentationIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier) NormalizedNode(org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode) LeafSchemaNode(org.opendaylight.yangtools.yang.model.api.LeafSchemaNode) AugmentationIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier) NormalizedNodeWriter(org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter) QName(org.opendaylight.yangtools.yang.common.QName) JSONNormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter) ForwardingNormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter) XMLStreamNormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter) NormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) NodeIdentifierWithPredicates(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates) MapEntryNode(org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode) XMLStreamException(javax.xml.stream.XMLStreamException) SchemaPath(org.opendaylight.yangtools.yang.model.api.SchemaPath) XMLStreamWriter(javax.xml.stream.XMLStreamWriter) NodeIdentifier(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier) ForwardingNormalizedNodeStreamWriter(org.opendaylight.yangtools.yang.data.api.schema.stream.ForwardingNormalizedNodeStreamWriter) SchemaContext(org.opendaylight.yangtools.yang.model.api.SchemaContext) NormalizedNode(org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode) FactoryConfigurationError(javax.xml.stream.FactoryConfigurationError)

Example 27 with DataNodeContainer

use of org.opendaylight.yangtools.yang.model.api.DataNodeContainer in project netconf by opendaylight.

the class XmlNormalizedNodeBodyReader method findPathToSchemaNodeByName.

private static Deque<Object> findPathToSchemaNodeByName(final DataSchemaNode schemaNode, final String elementName, final String namespace) {
    final Deque<Object> result = new ArrayDeque<>();
    final ArrayList<ChoiceSchemaNode> choiceSchemaNodes = new ArrayList<>();
    for (final DataSchemaNode child : ((DataNodeContainer) schemaNode).getChildNodes()) {
        if (child instanceof ChoiceSchemaNode) {
            choiceSchemaNodes.add((ChoiceSchemaNode) child);
        } else if (child.getQName().getLocalName().equalsIgnoreCase(elementName) && child.getQName().getNamespace().toString().equalsIgnoreCase(namespace)) {
            // add child to result
            result.push(child);
            // find augmentation
            if (child.isAugmenting()) {
                final AugmentationSchemaNode augment = findCorrespondingAugment(schemaNode, child);
                if (augment != null) {
                    result.push(augment);
                }
            }
            // return result
            return result;
        }
    }
    for (final ChoiceSchemaNode choiceNode : choiceSchemaNodes) {
        for (final CaseSchemaNode caseNode : choiceNode.getCases()) {
            final Deque<Object> resultFromRecursion = findPathToSchemaNodeByName(caseNode, elementName, namespace);
            if (!resultFromRecursion.isEmpty()) {
                resultFromRecursion.push(choiceNode);
                if (choiceNode.isAugmenting()) {
                    final AugmentationSchemaNode augment = findCorrespondingAugment(schemaNode, choiceNode);
                    if (augment != null) {
                        resultFromRecursion.push(augment);
                    }
                }
                return resultFromRecursion;
            }
        }
    }
    return result;
}
Also used : AugmentationSchemaNode(org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode) DataSchemaNode(org.opendaylight.yangtools.yang.model.api.DataSchemaNode) ArrayList(java.util.ArrayList) CaseSchemaNode(org.opendaylight.yangtools.yang.model.api.CaseSchemaNode) DataNodeContainer(org.opendaylight.yangtools.yang.model.api.DataNodeContainer) ChoiceSchemaNode(org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode) ArrayDeque(java.util.ArrayDeque)

Example 28 with DataNodeContainer

use of org.opendaylight.yangtools.yang.model.api.DataNodeContainer in project netconf by opendaylight.

the class BaseYangSwaggerGenerator method createPath.

private String createPath(final DataSchemaNode schemaNode, final ArrayNode pathParams, final OAversion oaversion, final String localName) {
    final StringBuilder path = new StringBuilder();
    path.append(localName);
    if (schemaNode instanceof ListSchemaNode) {
        final ListPathBuilder keyBuilder = newListPathBuilder();
        for (final QName listKey : ((ListSchemaNode) schemaNode).getKeyDefinition()) {
            final String paramName = createUniquePathParamName(listKey.getLocalName(), pathParams);
            final String pathParamIdentifier = keyBuilder.nextParamIdentifier(paramName);
            path.append(pathParamIdentifier);
            final ObjectNode pathParam = JsonNodeFactory.instance.objectNode();
            pathParam.put("name", paramName);
            ((DataNodeContainer) schemaNode).findDataChildByName(listKey).flatMap(DataSchemaNode::getDescription).ifPresent(desc -> pathParam.put("description", desc));
            final ObjectNode typeParent = getTypeParentNode(pathParam, oaversion);
            typeParent.put("type", "string");
            pathParam.put("in", "path");
            pathParam.put("required", true);
            pathParams.add(pathParam);
        }
    }
    return path.toString();
}
Also used : ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) QName(org.opendaylight.yangtools.yang.common.QName) ListSchemaNode(org.opendaylight.yangtools.yang.model.api.ListSchemaNode) DataNodeContainer(org.opendaylight.yangtools.yang.model.api.DataNodeContainer)

Example 29 with DataNodeContainer

use of org.opendaylight.yangtools.yang.model.api.DataNodeContainer in project netconf by opendaylight.

the class DefinitionGenerator method processModule.

private void processModule(final Module module, final ObjectNode definitions, final DefinitionNames definitionNames, final EffectiveModelContext schemaContext, final OAversion oaversion) {
    final ObjectNode definition = JsonNodeFactory.instance.objectNode();
    final ObjectNode properties = JsonNodeFactory.instance.objectNode();
    final ArrayNode required = JsonNodeFactory.instance.arrayNode();
    final String moduleName = module.getName();
    final String definitionName = moduleName + MODULE_NAME_SUFFIX;
    final SchemaInferenceStack stack = SchemaInferenceStack.of(schemaContext);
    for (final DataSchemaNode node : module.getChildNodes()) {
        stack.enterSchemaTree(node.getQName());
        final String localName = node.getQName().getLocalName();
        if (node.isConfiguration()) {
            if (node instanceof ContainerSchemaNode || node instanceof ListSchemaNode) {
                for (final DataSchemaNode childNode : ((DataNodeContainer) node).getChildNodes()) {
                    final ObjectNode childNodeProperties = JsonNodeFactory.instance.objectNode();
                    final String ref = getAppropriateModelPrefix(oaversion) + moduleName + CONFIG + "_" + localName + definitionNames.getDiscriminator(node);
                    if (node instanceof ListSchemaNode) {
                        childNodeProperties.put(TYPE_KEY, ARRAY_TYPE);
                        final ObjectNode items = JsonNodeFactory.instance.objectNode();
                        items.put(REF_KEY, ref);
                        childNodeProperties.set(ITEMS_KEY, items);
                        childNodeProperties.put(DESCRIPTION_KEY, childNode.getDescription().orElse(""));
                        childNodeProperties.put(TITLE_KEY, localName + CONFIG);
                    } else {
                        /*
                            Description can't be added, because nothing allowed alongside $ref.
                            allOf is not an option, because ServiceNow can't parse it.
                          */
                        childNodeProperties.put(REF_KEY, ref);
                    }
                    // add module name prefix to property name, when ServiceNow can process colons
                    properties.set(localName, childNodeProperties);
                }
            } else {
                if (node instanceof LeafSchemaNode) {
                    /*
                            Add module name prefix to property name, when ServiceNow can process colons(second parameter
                            of processLeafNode).
                         */
                    processLeafNode((LeafSchemaNode) node, localName, properties, required, stack, definitions, definitionNames, oaversion);
                }
            }
        }
        stack.exit();
    }
    definition.put(TITLE_KEY, definitionName);
    definition.put(TYPE_KEY, OBJECT_TYPE);
    definition.set(PROPERTIES_KEY, properties);
    definition.put(DESCRIPTION_KEY, module.getDescription().orElse(""));
    setRequiredIfNotEmpty(definition, required);
    definitions.set(definitionName, definition);
}
Also used : SchemaInferenceStack(org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack) ContainerSchemaNode(org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) DataSchemaNode(org.opendaylight.yangtools.yang.model.api.DataSchemaNode) ListSchemaNode(org.opendaylight.yangtools.yang.model.api.ListSchemaNode) LeafListSchemaNode(org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode) DataNodeContainer(org.opendaylight.yangtools.yang.model.api.DataNodeContainer) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) LeafSchemaNode(org.opendaylight.yangtools.yang.model.api.LeafSchemaNode)

Example 30 with DataNodeContainer

use of org.opendaylight.yangtools.yang.model.api.DataNodeContainer in project netconf by opendaylight.

the class BaseYangSwaggerGenerator method addPaths.

private void addPaths(final DataSchemaNode node, final Optional<String> deviceName, final String moduleName, final ObjectNode paths, final ArrayNode parentPathParams, final EffectiveModelContext schemaContext, final boolean isConfig, final String parentName, final DefinitionNames definitionNames, final URIType uriType, final OAversion oaversion, final String resourcePath) {
    LOG.debug("Adding path: [{}]", resourcePath);
    final ArrayNode pathParams = JsonUtil.copy(parentPathParams);
    Iterable<? extends DataSchemaNode> childSchemaNodes = Collections.emptySet();
    if (node instanceof ListSchemaNode || node instanceof ContainerSchemaNode) {
        final DataNodeContainer dataNodeContainer = (DataNodeContainer) node;
        childSchemaNodes = dataNodeContainer.getChildNodes();
    }
    final ObjectNode path = JsonNodeFactory.instance.objectNode();
    path.setAll(operations(node, moduleName, deviceName, pathParams, isConfig, parentName, definitionNames, uriType, oaversion));
    paths.set(resourcePath, path);
    if (uriType.equals(URIType.RFC8040)) {
        ((ActionNodeContainer) node).getActions().forEach(actionDef -> {
            final String resolvedPath = "rests/operations" + resourcePath.substring(11) + "/" + resolvePathArgumentsName(actionDef.getQName(), node.getQName(), schemaContext);
            addOperations(actionDef, moduleName, deviceName, paths, parentName, definitionNames, oaversion, resolvedPath);
        });
    }
    for (final DataSchemaNode childNode : childSchemaNodes) {
        if (childNode instanceof ListSchemaNode || childNode instanceof ContainerSchemaNode) {
            final String newParent = parentName + "_" + node.getQName().getLocalName();
            final String localName = resolvePathArgumentsName(childNode.getQName(), node.getQName(), schemaContext);
            final String newResourcePath = resourcePath + "/" + createPath(childNode, pathParams, oaversion, localName);
            if (uriType.equals(URIType.RFC8040)) {
                final boolean newIsConfig = isConfig && childNode.isConfiguration();
                addPaths(childNode, deviceName, moduleName, paths, pathParams, schemaContext, newIsConfig, newParent, definitionNames, uriType, oaversion, newResourcePath);
            } else {
                if (!isConfig || childNode.isConfiguration()) {
                    addPaths(childNode, deviceName, moduleName, paths, pathParams, schemaContext, isConfig, newParent, definitionNames, uriType, oaversion, newResourcePath);
                }
            }
        }
    }
}
Also used : ContainerSchemaNode(org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) DataSchemaNode(org.opendaylight.yangtools.yang.model.api.DataSchemaNode) ListSchemaNode(org.opendaylight.yangtools.yang.model.api.ListSchemaNode) DataNodeContainer(org.opendaylight.yangtools.yang.model.api.DataNodeContainer) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode)

Aggregations

DataNodeContainer (org.opendaylight.yangtools.yang.model.api.DataNodeContainer)41 DataSchemaNode (org.opendaylight.yangtools.yang.model.api.DataSchemaNode)34 QName (org.opendaylight.yangtools.yang.common.QName)15 ListSchemaNode (org.opendaylight.yangtools.yang.model.api.ListSchemaNode)14 YangInstanceIdentifier (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)12 ChoiceSchemaNode (org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode)12 CaseSchemaNode (org.opendaylight.yangtools.yang.model.api.CaseSchemaNode)11 ContainerSchemaNode (org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode)10 LeafListSchemaNode (org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode)9 LeafSchemaNode (org.opendaylight.yangtools.yang.model.api.LeafSchemaNode)9 ArrayList (java.util.ArrayList)7 NodeIdentifier (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier)7 RestConfModule (org.opendaylight.netconf.sal.rest.api.Draft02.RestConfModule)6 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)5 Test (org.junit.Test)5 AugmentationSchemaNode (org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode)5 Module (org.opendaylight.yangtools.yang.model.api.Module)5 ContainerNode (org.opendaylight.yangtools.yang.data.api.schema.ContainerNode)4 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)3 ArrayDeque (java.util.ArrayDeque)3