X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-data-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fdata%2Fimpl%2Fschema%2FImmutableNormalizedNodeStreamWriter.java;h=d8b9dc438e17282277b1941dff256d14ac82fb87;hb=78db01f74de82201a6803951b025f783cd8c0ad8;hp=bb24d867b26f1ee3516ec5583d395c91c75da050;hpb=4d58584e1a9a4250c2c3bd633002d4020d060705;p=yangtools.git diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNormalizedNodeStreamWriter.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNormalizedNodeStreamWriter.java index bb24d867b2..d8b9dc438e 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNormalizedNodeStreamWriter.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNormalizedNodeStreamWriter.java @@ -11,38 +11,28 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; +import java.io.IOException; import java.util.ArrayDeque; -import java.util.Collection; import java.util.Deque; import javax.xml.transform.dom.DOMSource; import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.yangtools.odlext.model.api.YangModeledAnyXmlSchemaNode; +import org.opendaylight.yangtools.odlext.model.api.YangModeledAnyxmlSchemaNode; 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.NodeWithValue; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; -import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; -import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; -import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; -import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode; -import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode; -import org.opendaylight.yangtools.yang.data.api.schema.YangModeledAnyXmlNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAnyXmlNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAnydataNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder; @@ -65,15 +55,18 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; *

* Other mode of operation is using {@link #from(NormalizedNodeContainerBuilder)}, where all created nodes will be * written to this builder. + * + *

+ * This class is not final for purposes of customization, normal users should not need to subclass it. */ public class ImmutableNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter { - @SuppressWarnings("rawtypes") private final Deque builders = new ArrayDeque<>(); + private DataSchemaNode nextSchema; @SuppressWarnings("rawtypes") - protected ImmutableNormalizedNodeStreamWriter(final NormalizedNodeContainerBuilder topLevelBuilder) { + protected ImmutableNormalizedNodeStreamWriter(final NormalizedNodeBuilder topLevelBuilder) { builders.push(topLevelBuilder); } @@ -114,235 +107,144 @@ public class ImmutableNormalizedNodeStreamWriter implements NormalizedNodeStream * @param result {@link NormalizedNodeResult} object which will hold result value. * @return {@link NormalizedNodeStreamWriter} which will write item to supplied result holder. */ - public static NormalizedNodeStreamWriter from(final NormalizedNodeResult result) { - return new ImmutableNormalizedNodeStreamWriter(result); - } - - @SuppressWarnings("rawtypes") - protected NormalizedNodeBuilder getCurrent() { - return builders.peek(); - } - - @SuppressWarnings("rawtypes") - protected final NormalizedNodeContainerBuilder getCurrentContainer() { - final NormalizedNodeBuilder current = getCurrent(); - if (current == null) { - return null; - } - checkState(current instanceof NormalizedNodeContainerBuilder, "%s is not a node container", current); - return (NormalizedNodeContainerBuilder) current; - } - - @SuppressWarnings("rawtypes") - protected NormalizedNodeBuilder getCurrentScalar() { - final NormalizedNodeBuilder current = getCurrent(); - checkState(!(current instanceof NormalizedNodeContainerBuilder), "Unexpected node container %s", current); - return current; - } - - @SuppressWarnings("rawtypes") - private void enter(final NormalizedNodeBuilder next) { - builders.push(next); - nextSchema = null; - } - - @SuppressWarnings("unchecked") - protected void writeChild(final NormalizedNode child) { - getCurrentContainer().addChild(child); + public static @NonNull NormalizedNodeStreamWriter from(final NormalizedNodeResult result) { + return result instanceof NormalizedNodeMetadataResult ? from((NormalizedNodeMetadataResult) result) + : new ImmutableNormalizedNodeStreamWriter(result); } - @Override - @SuppressWarnings({"rawtypes","unchecked"}) - public void endNode() { - final NormalizedNodeBuilder finishedBuilder = builders.poll(); - checkState(finishedBuilder != null, "Node which should be closed does not exists."); - final NormalizedNodeContainerBuilder current = getCurrentContainer(); - checkState(current != null, "Reached top level node, which could not be closed in this writer."); - final NormalizedNode product = finishedBuilder.build(); - current.addChild(product); - nextSchema = null; + /** + * Creates a {@link NormalizedNodeStreamWriter} which creates one instance of top-level {@link NormalizedNode} + * (type of NormalizedNode) is determined by first start event. + * + *

+ * Result is built when {@link #endNode()} associated with that start event is emitted. + * + *

+ * Writer properly creates also nested {@link NormalizedNode} instances, if their are supported inside the scope + * of the first event. + * + *

+ * This method is useful for clients, which knows there will be one top-level node written, but does not know which + * type of {@link NormalizedNode} will be written. + * + * @param result {@link NormalizedNodeResult} object which will hold result value. + * @return {@link NormalizedNodeStreamWriter} which will write item to supplied result holder. + */ + public static @NonNull NormalizedNodeStreamWriter from(final NormalizedNodeMetadataResult result) { + return new ImmutableMetadataNormalizedNodeStreamWriter(result); } @Override public void startLeafNode(final NodeIdentifier name) { checkDataNodeContainer(); - enter(InterningLeafNodeBuilder.forSchema(nextSchema).withNodeIdentifier(name)); + enter(name, leafNodeBuilder(nextSchema)); nextSchema = null; } @Override public void startLeafSet(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - final ListNodeBuilder> builder = UNKNOWN_SIZE == childSizeHint - ? InterningLeafSetNodeBuilder.create(nextSchema) - : InterningLeafSetNodeBuilder.create(nextSchema, childSizeHint); - builder.withNodeIdentifier(name); - enter(builder); + enter(name, UNKNOWN_SIZE == childSizeHint ? InterningLeafSetNodeBuilder.create(nextSchema) + : InterningLeafSetNodeBuilder.create(nextSchema, childSizeHint)); } @Override public void startLeafSetEntryNode(final NodeWithValue name) { - @SuppressWarnings("rawtypes") - final NormalizedNodeBuilder current = getCurrent(); - checkArgument(current instanceof ImmutableOrderedLeafSetNodeBuilder - || current instanceof ImmutableLeafSetNodeBuilder, "LeafSetEntryNode is not valid for parent %s", current); - enter(ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(name)); + final NormalizedNodeBuilder current = current(); + checkArgument(current instanceof ImmutableLeafSetNodeBuilder + || current instanceof ImmutableOrderedLeafSetNodeBuilder || current instanceof NormalizedNodeResultBuilder, + "LeafSetEntryNode is not valid for parent %s", current); + enter(name, leafsetEntryNodeBuilder()); nextSchema = null; } @Override public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - final ListNodeBuilder> builder = Builders.orderedLeafSetBuilder(); - builder.withNodeIdentifier(name); - enter(builder); + enter(name, Builders.orderedLeafSetBuilder()); } @Override - public void startAnyxmlNode(final NodeIdentifier name) { + public boolean startAnyxmlNode(final NodeIdentifier name, final Class objectModel) { checkDataNodeContainer(); - enter(ImmutableAnyXmlNodeBuilder.create().withNodeIdentifier(name)); - nextSchema = null; + if (DOMSource.class.isAssignableFrom(objectModel)) { + enter(name, ImmutableAnyXmlNodeBuilder.create()); + nextSchema = null; + return true; + } + return false; } @Override public void startContainerNode(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - - final DataContainerNodeAttrBuilder builder = - UNKNOWN_SIZE == childSizeHint ? ImmutableContainerNodeBuilder.create() - : ImmutableContainerNodeBuilder.create(childSizeHint); - enter(builder.withNodeIdentifier(name)); + enter(name, UNKNOWN_SIZE == childSizeHint ? ImmutableContainerNodeBuilder.create() + : ImmutableContainerNodeBuilder.create(childSizeHint)); } @Override public void startYangModeledAnyXmlNode(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - checkArgument(nextSchema instanceof YangModeledAnyXmlSchemaNode, - "Schema of this node should be instance of YangModeledAnyXmlSchemaNode"); - final DataContainerNodeAttrBuilder builder = - UNKNOWN_SIZE == childSizeHint - ? ImmutableYangModeledAnyXmlNodeBuilder.create((YangModeledAnyXmlSchemaNode) nextSchema) - : ImmutableYangModeledAnyXmlNodeBuilder.create( - (YangModeledAnyXmlSchemaNode) nextSchema, childSizeHint); - enter(builder.withNodeIdentifier(name)); + checkArgument(nextSchema instanceof YangModeledAnyxmlSchemaNode, + "Schema of this node should be instance of YangModeledAnyxmlSchemaNode"); + final YangModeledAnyxmlSchemaNode anyxmlSchema = (YangModeledAnyxmlSchemaNode) nextSchema; + enter(name, UNKNOWN_SIZE == childSizeHint ? ImmutableYangModeledAnyXmlNodeBuilder.create(anyxmlSchema) + : ImmutableYangModeledAnyXmlNodeBuilder.create(anyxmlSchema, childSizeHint)); } @Override public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - - final CollectionNodeBuilder builder = - UNKNOWN_SIZE == childSizeHint ? ImmutableUnkeyedListNodeBuilder.create() - : ImmutableUnkeyedListNodeBuilder.create(childSizeHint); - enter(builder.withNodeIdentifier(name)); + enter(name, UNKNOWN_SIZE == childSizeHint ? ImmutableUnkeyedListNodeBuilder.create() + : ImmutableUnkeyedListNodeBuilder.create(childSizeHint)); } @Override public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) { - checkArgument(getCurrent() instanceof NormalizedNodeResultBuilder - || getCurrent() instanceof ImmutableUnkeyedListNodeBuilder); - final DataContainerNodeAttrBuilder builder = - UNKNOWN_SIZE == childSizeHint ? ImmutableUnkeyedListEntryNodeBuilder.create() - : ImmutableUnkeyedListEntryNodeBuilder.create(childSizeHint); - enter(builder.withNodeIdentifier(name)); + final NormalizedNodeBuilder current = current(); + checkArgument(current instanceof ImmutableUnkeyedListNodeBuilder + || current instanceof NormalizedNodeResultBuilder); + enter(name, UNKNOWN_SIZE == childSizeHint ? ImmutableUnkeyedListEntryNodeBuilder.create() + : ImmutableUnkeyedListEntryNodeBuilder.create(childSizeHint)); } @Override public void startMapNode(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - - final CollectionNodeBuilder builder = UNKNOWN_SIZE == childSizeHint - ? ImmutableMapNodeBuilder.create() : ImmutableMapNodeBuilder.create(childSizeHint); - enter(builder.withNodeIdentifier(name)); + enter(name, UNKNOWN_SIZE == childSizeHint ? ImmutableMapNodeBuilder.create() + : ImmutableMapNodeBuilder.create(childSizeHint)); } @Override public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) { - if (!(getCurrent() instanceof NormalizedNodeResultBuilder)) { - checkArgument(getCurrent() instanceof ImmutableMapNodeBuilder - || getCurrent() instanceof ImmutableOrderedMapNodeBuilder); - } + final NormalizedNodeBuilder current = current(); + checkArgument(current instanceof ImmutableMapNodeBuilder || current instanceof ImmutableOrderedMapNodeBuilder + || current instanceof NormalizedNodeResultBuilder); - final DataContainerNodeAttrBuilder builder = - UNKNOWN_SIZE == childSizeHint ? ImmutableMapEntryNodeBuilder.create() - : ImmutableMapEntryNodeBuilder.create(childSizeHint); - enter(builder.withNodeIdentifier(identifier)); + enter(identifier, UNKNOWN_SIZE == childSizeHint ? ImmutableMapEntryNodeBuilder.create() + : ImmutableMapEntryNodeBuilder.create(childSizeHint)); } @Override public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - - final CollectionNodeBuilder builder = UNKNOWN_SIZE == childSizeHint - ? ImmutableOrderedMapNodeBuilder.create() : ImmutableOrderedMapNodeBuilder.create(childSizeHint); - enter(builder.withNodeIdentifier(name)); + enter(name, UNKNOWN_SIZE == childSizeHint ? ImmutableOrderedMapNodeBuilder.create() + : ImmutableOrderedMapNodeBuilder.create(childSizeHint)); } @Override public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) { checkDataNodeContainer(); - - final DataContainerNodeBuilder builder = UNKNOWN_SIZE == childSizeHint - ? ImmutableChoiceNodeBuilder.create() : ImmutableChoiceNodeBuilder.create(childSizeHint); - enter(builder.withNodeIdentifier(name)); + enter(name, UNKNOWN_SIZE == childSizeHint ? ImmutableChoiceNodeBuilder.create() + : ImmutableChoiceNodeBuilder.create(childSizeHint)); } @Override public void startAugmentationNode(final AugmentationIdentifier identifier) { checkDataNodeContainer(); - checkArgument(!(getCurrent() instanceof ImmutableAugmentationNodeBuilder)); - enter(Builders.augmentationBuilder().withNodeIdentifier(identifier)); - } - - private void checkDataNodeContainer() { - @SuppressWarnings("rawtypes") - final NormalizedNodeContainerBuilder current = getCurrentContainer(); - if (!(current instanceof NormalizedNodeResultBuilder)) { - checkArgument(current instanceof DataContainerNodeBuilder, "Invalid nesting of data."); - } - } - - @SuppressWarnings("rawtypes") - protected static final class NormalizedNodeResultBuilder implements NormalizedNodeContainerBuilder { - - private final NormalizedNodeResult result; - - public NormalizedNodeResultBuilder(final NormalizedNodeResult result) { - this.result = result; - } - - @Override - public NormalizedNodeBuilder withValue(final Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public NormalizedNodeContainerBuilder withValue(final Collection value) { - throw new UnsupportedOperationException(); - } - - @Override - public NormalizedNode build() { - throw new IllegalStateException("Can not close NormalizedNodeResult"); - } - - @Override - public NormalizedNodeContainerBuilder withNodeIdentifier(final PathArgument nodeIdentifier) { - throw new UnsupportedOperationException(); - } - - @Override - public NormalizedNodeContainerBuilder addChild(final NormalizedNode child) { - result.setResult(child); - return this; - } - - @Override - public NormalizedNodeContainerBuilder removeChild(final PathArgument key) { - throw new UnsupportedOperationException(); - } + checkArgument(!(current() instanceof ImmutableAugmentationNodeBuilder)); + enter(identifier, Builders.augmentationBuilder()); } @Override @@ -362,11 +264,105 @@ public class ImmutableNormalizedNodeStreamWriter implements NormalizedNodeStream @Override public void scalarValue(final Object value) { - getCurrentScalar().withValue(value); + currentScalar().withValue(value); } @Override public void domSourceValue(final DOMSource value) { - getCurrentScalar().withValue(value); + currentScalar().withValue(value); + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void endNode() { + final NormalizedNodeBuilder finishedBuilder = builders.poll(); + checkState(finishedBuilder != null, "Node which should be closed does not exists."); + final NormalizedNode product = finishedBuilder.build(); + nextSchema = null; + + writeChild(product); + } + + @Override + public boolean startAnydataNode(final NodeIdentifier name, final Class objectModel) throws IOException { + checkDataNodeContainer(); + enter(name, ImmutableAnydataNodeBuilder.create(objectModel)); + // We support all object models + return true; + } + + /** + * Add a child not to the currently-open builder. + * + * @param child A new child + * @throws NullPointerException if {@code child} is null + * @throws IllegalStateException if there is no open builder + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected final void writeChild(final NormalizedNode child) { + final NormalizedNodeContainerBuilder current = currentContainer(); + checkState(current != null, "Reached top level node, which could not be closed in this writer."); + current.addChild(requireNonNull(child)); + } + + // Exposed for ImmutableMetadataNormalizedNodeStreamWriter + @SuppressWarnings("rawtypes") + void enter(final PathArgument identifier, final NormalizedNodeBuilder next) { + builders.push(next.withNodeIdentifier(identifier)); + nextSchema = null; + } + + // Exposed for ImmutableMetadataNormalizedNodeStreamWriter + protected final NormalizedNodeBuilder popBuilder() { + return builders.pop(); + } + + final void reset(final NormalizedNodeResultBuilder builder) { + nextSchema = null; + builders.clear(); + builders.push(builder); + } + + private ImmutableLeafNodeBuilder leafNodeBuilder(final DataSchemaNode schema) { + final InterningLeafNodeBuilder interning = InterningLeafNodeBuilder.forSchema(schema); + return interning != null ? interning : leafNodeBuilder(); + } + + ImmutableLeafNodeBuilder leafNodeBuilder() { + return new ImmutableLeafNodeBuilder<>(); + } + + ImmutableLeafSetEntryNodeBuilder leafsetEntryNodeBuilder() { + return ImmutableLeafSetEntryNodeBuilder.create(); + } + + private void checkDataNodeContainer() { + @SuppressWarnings("rawtypes") + final NormalizedNodeContainerBuilder current = currentContainer(); + if (!(current instanceof NormalizedNodeResultBuilder)) { + checkArgument(current instanceof DataContainerNodeBuilder, "Invalid nesting of data."); + } + } + + @SuppressWarnings("rawtypes") + private NormalizedNodeBuilder current() { + return builders.peek(); + } + + @SuppressWarnings("rawtypes") + private NormalizedNodeContainerBuilder currentContainer() { + final NormalizedNodeBuilder current = current(); + if (current == null) { + return null; + } + checkState(current instanceof NormalizedNodeContainerBuilder, "%s is not a node container", current); + return (NormalizedNodeContainerBuilder) current; + } + + @SuppressWarnings("rawtypes") + private NormalizedNodeBuilder currentScalar() { + final NormalizedNodeBuilder current = current(); + checkState(!(current instanceof NormalizedNodeContainerBuilder), "Unexpected node container %s", current); + return current; } }