import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
-import static org.opendaylight.netconf.sal.rest.api.Draft02.RestConfModule.ERRORS_CONTAINER_QNAME;
-import com.google.common.collect.Iterables;
import com.google.gson.stream.JsonWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
-import java.util.stream.Collectors;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
-import org.opendaylight.netconf.sal.rest.api.Draft02.RestConfModule;
+import org.opendaylight.netconf.sal.rest.api.Draft02;
import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
import org.opendaylight.restconf.common.ErrorTags;
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
import org.opendaylight.restconf.common.errors.RestconfError;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.XMLNamespace;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final XMLOutputFactory XML_FACTORY;
- private static final YangInstanceIdentifier ERRORS = YangInstanceIdentifier.builder()
- .node(ERRORS_CONTAINER_QNAME)
- .node(ERRORS_CONTAINER_QNAME)
- .build();
-
static {
XML_FACTORY = XMLOutputFactory.newFactory();
XML_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
}
final Status status = ErrorTags.statusOf(errors.iterator().next().getErrorTag());
- final DataNodeContainer errorsSchemaNode =
- (DataNodeContainer) controllerContext.getRestconfModuleErrorsSchemaNode();
- if (errorsSchemaNode == null) {
+ final var errorsEntry = controllerContext.getRestconfModuleErrorsSchemaNode();
+ if (errorsEntry == null) {
return Response.status(status).type(MediaType.TEXT_PLAIN_TYPE).entity(exception.getMessage()).build();
}
- checkState(errorsSchemaNode instanceof ContainerSchemaNode, "Found Errors SchemaNode isn't ContainerNode");
+ final var errorsSchemaNode = errorsEntry.getValue();
final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> errContBuild =
- SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) errorsSchemaNode);
+ SchemaAwareBuilders.containerBuilder(errorsSchemaNode);
- final List<DataSchemaNode> schemaList = ControllerContext.findInstanceDataChildrenByName(errorsSchemaNode,
- RestConfModule.ERROR_LIST_SCHEMA_NODE);
- final DataSchemaNode errListSchemaNode = Iterables.getFirst(schemaList, null);
+ final var schemaList = ControllerContext.findInstanceDataChildrenByName(errorsSchemaNode,
+ Draft02.RestConfModule.ERROR_LIST_SCHEMA_NODE);
+ final DataSchemaNode errListSchemaNode = ControllerContext.getFirst(schemaList);
checkState(errListSchemaNode instanceof ListSchemaNode, "Found Error SchemaNode isn't ListSchemaNode");
final CollectionNodeBuilder<MapEntryNode, SystemMapNode> listErorsBuilder = SchemaAwareBuilders
.mapBuilder((ListSchemaNode) errListSchemaNode);
}
errContBuild.withChild(listErorsBuilder.build());
- final NormalizedNodeContext errContext = new NormalizedNodeContext(new InstanceIdentifierContext<>(ERRORS,
- (DataSchemaNode) errorsSchemaNode, null, controllerContext.getGlobalSchema()), errContBuild.build());
+ final NormalizedNodeContext errContext = new NormalizedNodeContext(
+ InstanceIdentifierContext.ofStack(errorsEntry.getKey(), null), errContBuild.build());
- Object responseBody;
+ final String responseBody;
if (mediaType.getSubtype().endsWith("json")) {
- responseBody = toJsonResponseBody(errContext, errorsSchemaNode);
+ responseBody = toJsonResponseBody(errContext);
} else {
- responseBody = toXMLResponseBody(errContext, errorsSchemaNode);
+ responseBody = toXMLResponseBody(errContext);
}
return Response.status(status).type(mediaType).entity(responseBody).build();
final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> errNodeValues = SchemaAwareBuilders
.mapEntryBuilder(listStreamSchemaNode);
- List<DataSchemaNode> lsChildDataSchemaNode = ControllerContext.findInstanceDataChildrenByName(
+ var lsChildDataSchemaNode = ControllerContext.findInstanceDataChildrenByName(
listStreamSchemaNode, "error-type");
- final DataSchemaNode errTypSchemaNode = Iterables.getFirst(lsChildDataSchemaNode, null);
+ final DataSchemaNode errTypSchemaNode = ControllerContext.getFirst(lsChildDataSchemaNode);
checkState(errTypSchemaNode instanceof LeafSchemaNode);
errNodeValues.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) errTypSchemaNode)
.withValue(error.getErrorType().elementBody()).build());
lsChildDataSchemaNode = ControllerContext.findInstanceDataChildrenByName(
listStreamSchemaNode, "error-tag");
- final DataSchemaNode errTagSchemaNode = Iterables.getFirst(lsChildDataSchemaNode, null);
+ final DataSchemaNode errTagSchemaNode = ControllerContext.getFirst(lsChildDataSchemaNode);
checkState(errTagSchemaNode instanceof LeafSchemaNode);
errNodeValues.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) errTagSchemaNode)
.withValue(error.getErrorTag().elementBody()).build());
if (error.getErrorAppTag() != null) {
lsChildDataSchemaNode = ControllerContext.findInstanceDataChildrenByName(
listStreamSchemaNode, "error-app-tag");
- final DataSchemaNode errAppTagSchemaNode = Iterables.getFirst(lsChildDataSchemaNode, null);
+ final DataSchemaNode errAppTagSchemaNode = ControllerContext.getFirst(lsChildDataSchemaNode);
checkState(errAppTagSchemaNode instanceof LeafSchemaNode);
errNodeValues.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) errAppTagSchemaNode)
.withValue(error.getErrorAppTag()).build());
lsChildDataSchemaNode = ControllerContext.findInstanceDataChildrenByName(
listStreamSchemaNode, "error-message");
- final DataSchemaNode errMsgSchemaNode = Iterables.getFirst(lsChildDataSchemaNode, null);
+ final DataSchemaNode errMsgSchemaNode = ControllerContext.getFirst(lsChildDataSchemaNode);
checkState(errMsgSchemaNode instanceof LeafSchemaNode);
errNodeValues.withChild(SchemaAwareBuilders.leafBuilder((LeafSchemaNode) errMsgSchemaNode)
.withValue(error.getErrorMessage()).build());
// Oddly, error-info is defined as an empty container in the restconf yang. Apparently the
// intention is for implementors to define their own data content so we'll just treat it as a leaf
// with string data.
- errNodeValues.withChild(ImmutableNodes.leafNode(RestConfModule.ERROR_INFO_QNAME,
+ errNodeValues.withChild(ImmutableNodes.leafNode(Draft02.RestConfModule.ERROR_INFO_QNAME,
error.getErrorInfo()));
}
return errNodeValues.build();
}
- private static Object toJsonResponseBody(final NormalizedNodeContext errorsNode,
- final DataNodeContainer errorsSchemaNode) {
+ private static String toJsonResponseBody(final NormalizedNodeContext errorsNode) {
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
NormalizedNode data = errorsNode.getData();
- final InstanceIdentifierContext<?> context = errorsNode.getInstanceIdentifierContext();
+ final InstanceIdentifierContext context = errorsNode.getInstanceIdentifierContext();
final DataSchemaNode schema = (DataSchemaNode) context.getSchemaNode();
final OutputStreamWriter outputWriter = new OutputStreamWriter(outStream, StandardCharsets.UTF_8);
throw new RestconfDocumentedException(Response.Status.NOT_FOUND);
}
- boolean isDataRoot = false;
- XMLNamespace initialNs = null;
- SchemaPath path;
- if (context.getSchemaNode() instanceof SchemaContext) {
+ final boolean isDataRoot;
+ final var stack = context.inference().toSchemaInferenceStack();
+ if (stack.isEmpty()) {
isDataRoot = true;
- path = SchemaPath.ROOT;
} else {
- final List<QName> qNames = context.getInstanceIdentifier().getPathArguments().stream()
- .filter(arg -> !(arg instanceof NodeIdentifierWithPredicates))
- .filter(arg -> !(arg instanceof AugmentationIdentifier))
- .map(PathArgument::getNodeType)
- .collect(Collectors.toList());
- path = SchemaPath.of(Absolute.of(qNames)).getParent();
+ isDataRoot = false;
+ stack.exit();
+ // FIXME: Add proper handling of reading root.
}
+
+ XMLNamespace initialNs = null;
if (!schema.isAugmenting() && !(schema instanceof SchemaContext)) {
initialNs = schema.getQName().getNamespace();
}
final JsonWriter jsonWriter = JsonWriterFactory.createJsonWriter(outputWriter);
final NormalizedNodeStreamWriter jsonStreamWriter = JSONNormalizedNodeStreamWriter.createExclusiveWriter(
- JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(context.getSchemaContext()), path,
- initialNs, jsonWriter);
+ JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(context.getSchemaContext()),
+ stack.toInference(), initialNs, jsonWriter);
// 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
@Override
public void startLeafNode(final NodeIdentifier name) throws IOException {
- if (name.getNodeType().equals(RestConfModule.ERROR_INFO_QNAME)) {
+ if (name.getNodeType().equals(Draft02.RestConfModule.ERROR_INFO_QNAME)) {
inOurLeaf = true;
- jsonWriter.name(RestConfModule.ERROR_INFO_QNAME.getLocalName());
+ jsonWriter.name(Draft02.RestConfModule.ERROR_INFO_QNAME.getLocalName());
} else {
super.startLeafNode(name);
}
return outStream.toString(StandardCharsets.UTF_8);
}
- private static Object toXMLResponseBody(final NormalizedNodeContext errorsNode,
- final DataNodeContainer errorsSchemaNode) {
- final InstanceIdentifierContext<?> pathContext = errorsNode.getInstanceIdentifierContext();
+ private static String toXMLResponseBody(final NormalizedNodeContext errorsNode) {
+ final InstanceIdentifierContext pathContext = errorsNode.getInstanceIdentifierContext();
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
final XMLStreamWriter xmlWriter;
throw new IllegalStateException(e);
}
NormalizedNode data = errorsNode.getData();
- SchemaPath schemaPath;
- boolean isDataRoot = false;
- if (pathContext.getSchemaNode() instanceof SchemaContext) {
+
+ final boolean isDataRoot;
+ final var stack = pathContext.inference().toSchemaInferenceStack();
+ if (stack.isEmpty()) {
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();
+ isDataRoot = false;
+ stack.exit();
}
final NormalizedNodeStreamWriter xmlStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter,
- pathContext.getSchemaContext(), schemaPath);
+ stack.toInference());
// 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
@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();
+ if (name.getNodeType().equals(Draft02.RestConfModule.ERROR_INFO_QNAME)) {
+ String ns = Draft02.RestConfModule.ERROR_INFO_QNAME.getNamespace().toString();
try {
xmlWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX,
- RestConfModule.ERROR_INFO_QNAME.getLocalName(), ns);
+ Draft02.RestConfModule.ERROR_INFO_QNAME.getLocalName(), ns);
} catch (XMLStreamException e) {
throw new IOException("Error writing error-info", e);
}