From b7ff9cee91c9a0ff866994d2fefdea5de5b43053 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 27 May 2019 22:01:57 +0200 Subject: [PATCH] Cleanup NormalizedAnydata NormalizedAnydata is used only with conjuction with SchemaContext and DataSchemaNode, make sure users don't have to just through hoops. This also fixes SchemaTracker integration by providing a utility single-child parent for use with the specified context node as well as fixing support for streaming metadata. JIRA: YANGTOOLS-995 Change-Id: I11b4ac769c8d54faddc19eab3d094b2ba4f43aa3 Signed-off-by: Robert Varga --- .../data/util/MetadataNormalizedAnydata.java | 18 ++++-- .../gson/JSONNormalizedNodeStreamWriter.java | 20 +------ .../yang/data/codec/xml/DOMSourceAnydata.java | 15 +---- .../data/codec/xml/StreamWriterFacade.java | 20 +------ .../schema/AbstractNormalizableAnydata.java | 18 +++--- .../yang/data/util/NormalizableAnydata.java | 8 ++- .../yang/data/util/NormalizedAnydata.java | 35 +++++++---- .../util/SingleChildDataNodeContainer.java | 59 +++++++++++++++++++ 8 files changed, 119 insertions(+), 74 deletions(-) create mode 100644 yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/SingleChildDataNodeContainer.java diff --git a/yang/rfc7952-data-util/src/main/java/org/opendaylight/yangtools/rfc7952/data/util/MetadataNormalizedAnydata.java b/yang/rfc7952-data-util/src/main/java/org/opendaylight/yangtools/rfc7952/data/util/MetadataNormalizedAnydata.java index f614f1b19f..b544d3bd31 100644 --- a/yang/rfc7952-data-util/src/main/java/org/opendaylight/yangtools/rfc7952/data/util/MetadataNormalizedAnydata.java +++ b/yang/rfc7952-data-util/src/main/java/org/opendaylight/yangtools/rfc7952/data/util/MetadataNormalizedAnydata.java @@ -10,26 +10,32 @@ package org.opendaylight.yangtools.rfc7952.data.util; import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; +import java.io.IOException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.opendaylight.yangtools.rfc7952.data.api.NormalizedMetadata; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; -import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.util.NormalizedAnydata; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; @Beta @NonNullByDefault public final class MetadataNormalizedAnydata extends NormalizedAnydata { private final NormalizedMetadata metadata; - public MetadataNormalizedAnydata(final DataSchemaContextTree contextTree, - final DataSchemaContextNode contextNode, final NormalizedNode data, - final NormalizedMetadata metadata) { - super(contextTree, contextNode, data); + public MetadataNormalizedAnydata(final SchemaContext schemaContext, final DataSchemaNode contextNode, + final NormalizedNode data, final NormalizedMetadata metadata) { + super(schemaContext, contextNode, data); this.metadata = requireNonNull(metadata); } public NormalizedMetadata getMetadata() { return metadata; } + + @Override + public void writeTo(final NormalizedNodeStreamWriter writer, final boolean orderKeyLeaves) throws IOException { + NormalizedMetadataWriter.forStreamWriter(writer, orderKeyLeaves).write(getData(), metadata).flush(); + } } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java index d32bd2c8c5..940d8f4904 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java @@ -27,15 +27,13 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithV import org.opendaylight.yangtools.yang.data.api.schema.stream.AnydataExtension; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriterExtension; -import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker; import org.opendaylight.yangtools.yang.data.util.NormalizedAnydata; +import org.opendaylight.yangtools.yang.data.util.SingleChildDataNodeContainer; import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode; import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; 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.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; @@ -372,20 +370,8 @@ public abstract class JSONNormalizedNodeStreamWriter implements NormalizedNodeSt } private void writeNormalizedAnydata(final NormalizedAnydata anydata) throws IOException { - // TODO: this is rather ugly - final DataSchemaNode root = anydata.getContextTree().getRoot().getDataSchemaNode(); - if (!(root instanceof SchemaContext)) { - throw new IOException("Unexpected root context " + root); - } - - final DataSchemaNode node = anydata.getContextNode().getDataSchemaNode(); - if (!(node instanceof DataNodeContainer)) { - throw new IOException("Unexpected node context " + node); - } - - NormalizedNodeWriter.forStreamWriter(JSONNormalizedNodeStreamWriter.createNestedWriter( - codecs.rebaseTo((SchemaContext) root), (DataNodeContainer) node, context.getNamespace(), writer)).write( - anydata.getData()).flush(); + anydata.writeTo(JSONNormalizedNodeStreamWriter.createNestedWriter(codecs.rebaseTo(anydata.getSchemaContext()), + new SingleChildDataNodeContainer(anydata.getContextNode()), context.getNamespace(), writer)); } private void writeAnyXmlValue(final DOMSource anyXmlValue) throws IOException { diff --git a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/DOMSourceAnydata.java b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/DOMSourceAnydata.java index 90bc6abcf4..685f948d4d 100644 --- a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/DOMSourceAnydata.java +++ b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/DOMSourceAnydata.java @@ -17,8 +17,6 @@ import javax.xml.transform.dom.DOMSource; import org.eclipse.jdt.annotation.NonNullByDefault; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.impl.schema.AbstractNormalizableAnydata; -import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; -import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.xml.sax.SAXException; @@ -36,18 +34,11 @@ final class DOMSourceAnydata extends AbstractNormalizableAnydata { } @Override - protected void writeTo(final NormalizedNodeStreamWriter streamWriter, final DataSchemaContextTree contextTree, - final DataSchemaContextNode contextNode) throws IOException { - // TODO: this is rather ugly - final DataSchemaNode root = contextTree.getRoot().getDataSchemaNode(); - if (!(root instanceof SchemaContext)) { - throw new IOException("Unexpected root context " + root); - } - + protected void writeTo(final NormalizedNodeStreamWriter streamWriter, final SchemaContext schemaContext, + final DataSchemaNode contextNode) throws IOException { final XmlParserStream xmlParser; try { - xmlParser = XmlParserStream.create(streamWriter, (SchemaContext) root, - contextNode.getDataSchemaNode()); + xmlParser = XmlParserStream.create(streamWriter, schemaContext, contextNode); } catch (IllegalArgumentException e) { throw new IOException("Failed to instantiate XML parser", e); } diff --git a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/StreamWriterFacade.java b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/StreamWriterFacade.java index b2ec393abd..30cec9ca08 100644 --- a/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/StreamWriterFacade.java +++ b/yang/yang-data-codec-xml/src/main/java/org/opendaylight/yangtools/yang/data/codec/xml/StreamWriterFacade.java @@ -21,11 +21,8 @@ import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.util.NormalizedAnydata; -import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.data.util.SingleChildDataNodeContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -325,20 +322,9 @@ final class StreamWriterFacade extends ValueWriter { } void emitNormalizedAnydata(final NormalizedAnydata anydata) throws XMLStreamException { - // TODO: this is rather ugly - final DataSchemaNode root = anydata.getContextTree().getRoot().getDataSchemaNode(); - if (!(root instanceof SchemaContext)) { - throw new XMLStreamException("Unexpected root context " + root); - } - - final DataSchemaNode node = anydata.getContextNode().getDataSchemaNode(); - if (!(node instanceof DataNodeContainer)) { - throw new XMLStreamException("Unexpected node context " + node); - } - try { - NormalizedNodeWriter.forStreamWriter(XMLStreamNormalizedNodeStreamWriter.create(writer, - (SchemaContext) root, (DataNodeContainer) node), false).write(anydata.getData()).flush(); + anydata.writeTo(XMLStreamNormalizedNodeStreamWriter.create(writer, anydata.getSchemaContext(), + new SingleChildDataNodeContainer(anydata.getContextNode()))); } catch (IOException e) { throw new XMLStreamException("Failed to emit anydata " + anydata, e); } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/AbstractNormalizableAnydata.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/AbstractNormalizableAnydata.java index 1382f8413b..592890a041 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/AbstractNormalizableAnydata.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/AbstractNormalizableAnydata.java @@ -18,10 +18,10 @@ import org.opendaylight.yangtools.rfc7952.data.util.MetadataNormalizedAnydata; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.util.AnydataNormalizationException; -import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; -import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.data.util.NormalizableAnydata; import org.opendaylight.yangtools.yang.data.util.NormalizedAnydata; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; /** * Abstract base class for implementing the NormalizableAnydata interface. This class provides the binding to @@ -31,20 +31,20 @@ import org.opendaylight.yangtools.yang.data.util.NormalizedAnydata; @NonNullByDefault public abstract class AbstractNormalizableAnydata implements NormalizableAnydata { @Override - public final NormalizedAnydata normalizeTo(final DataSchemaContextTree contextTree, - final DataSchemaContextNode contextNode) throws AnydataNormalizationException { + public final NormalizedAnydata normalizeTo(final SchemaContext schemaContext, final DataSchemaNode contextNode) + throws AnydataNormalizationException { final NormalizedNodeMetadataResult result = new NormalizedNodeMetadataResult(); final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result); try { - writeTo(streamWriter, contextTree, contextNode); + writeTo(streamWriter, schemaContext, contextNode); } catch (IOException e) { throw new AnydataNormalizationException("Failed to normalize anydata", e); } final NormalizedNode data = result.getResult(); final Optional optMeta = result.getMetadata(); - return optMeta.isPresent() ? new MetadataNormalizedAnydata(contextTree, contextNode, data, optMeta.get()) - : new NormalizedAnydata(contextTree, contextNode, result.getResult()); + return optMeta.isPresent() ? new MetadataNormalizedAnydata(schemaContext, contextNode, data, optMeta.get()) + : new NormalizedAnydata(schemaContext, contextNode, result.getResult()); } @Override @@ -54,6 +54,6 @@ public abstract class AbstractNormalizableAnydata implements NormalizableAnydata protected abstract ToStringHelper addToStringAttributes(ToStringHelper helper); - protected abstract void writeTo(NormalizedNodeStreamWriter streamWriter, DataSchemaContextTree contextTree, - DataSchemaContextNode contextNode) throws IOException; + protected abstract void writeTo(NormalizedNodeStreamWriter streamWriter, SchemaContext schemaContext, + DataSchemaNode contextNode) throws IOException; } diff --git a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizableAnydata.java b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizableAnydata.java index f64ad00078..2e782b79a5 100644 --- a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizableAnydata.java +++ b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizableAnydata.java @@ -9,6 +9,8 @@ package org.opendaylight.yangtools.yang.data.util; import com.google.common.annotations.Beta; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; @Beta @NonNullByDefault @@ -16,12 +18,12 @@ public interface NormalizableAnydata { /** * Attempt to interpret this anydata content in the context of specified tree and node. * - * @param contextTree Data schema tree - * @param contextNode Data schema node + * @param schemaContext Schema context + * @param contextNode Corresponding schema node * @return Normalized anydata instance * @throws NullPointerException if any argument is null * @throws AnydataNormalizationException if this data cannot be interpreted in the requested context */ - NormalizedAnydata normalizeTo(DataSchemaContextTree contextTree, DataSchemaContextNode contextNode) + NormalizedAnydata normalizeTo(SchemaContext schemaContext, DataSchemaNode contextNode) throws AnydataNormalizationException; } diff --git a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizedAnydata.java b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizedAnydata.java index 7882470b37..d831822291 100644 --- a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizedAnydata.java +++ b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/NormalizedAnydata.java @@ -12,10 +12,16 @@ import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; +import java.io.IOException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; /** * The contents of an {@code anydata} node in a normalized format. This representation acts as a schema-bound bridge @@ -26,30 +32,39 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; */ @Beta @NonNullByDefault -public class NormalizedAnydata implements Immutable { - private final DataSchemaContextNode contextNode; - private final DataSchemaContextTree contextTree; +public class NormalizedAnydata implements Immutable, SchemaContextProvider { + private final SchemaContext schemaContext; + private final DataSchemaNode contextNode; private final NormalizedNode data; - public NormalizedAnydata(final DataSchemaContextTree contextTree, final DataSchemaContextNode contextNode, + public NormalizedAnydata(final SchemaContext schemaContext, final DataSchemaNode contextNode, final NormalizedNode data) { - this.contextTree = requireNonNull(contextTree); + this.schemaContext = requireNonNull(schemaContext); this.contextNode = requireNonNull(contextNode); this.data = requireNonNull(data); } - public final DataSchemaContextNode getContextNode() { - return contextNode; + @Override + public final SchemaContext getSchemaContext() { + return schemaContext; } - public final DataSchemaContextTree getContextTree() { - return contextTree; + public final DataSchemaNode getContextNode() { + return contextNode; } public final NormalizedNode getData() { return data; } + public final void writeTo(final NormalizedNodeStreamWriter writer) throws IOException { + writeTo(writer, true); + } + + public void writeTo(final NormalizedNodeStreamWriter writer, final boolean orderKeyLeaves) throws IOException { + NormalizedNodeWriter.forStreamWriter(writer, orderKeyLeaves).write(data).flush(); + } + @Override public final int hashCode() { return super.hashCode(); @@ -66,6 +81,6 @@ public class NormalizedAnydata implements Immutable { } protected ToStringHelper addToStringAttributes(final ToStringHelper helper) { - return helper.add("tree", contextTree).add("node", contextNode).add("data", data); + return helper.add("schemaConteext", schemaContext).add("node", contextNode).add("data", data); } } diff --git a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/SingleChildDataNodeContainer.java b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/SingleChildDataNodeContainer.java new file mode 100644 index 0000000000..f1a7f79421 --- /dev/null +++ b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/SingleChildDataNodeContainer.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.data.util; + +import static java.util.Objects.requireNonNull; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableSet; +import java.util.Collection; +import java.util.Optional; +import java.util.Set; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UsesNode; + +/** + * Utility DataNodeContainer containing only the specified node. + */ +@Beta +public final class SingleChildDataNodeContainer implements DataNodeContainer { + private final DataSchemaNode child; + + public SingleChildDataNodeContainer(final DataSchemaNode child) { + this.child = requireNonNull(child); + } + + @Override + public Optional findDataChildByName(final QName name) { + return child.getQName().equals(name) ? Optional.of(child) : Optional.empty(); + } + + @Override + public Collection getChildNodes() { + return ImmutableSet.of(child); + } + + @Override + public Set> getTypeDefinitions() { + return ImmutableSet.of(); + } + + @Override + public Set getGroupings() { + return ImmutableSet.of(); + } + + @Override + public Set getUses() { + return ImmutableSet.of(); + } +} -- 2.36.6