From 8485b8c8ca9481cc8797b08d56930bbf67c7653d Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Wed, 22 Apr 2015 09:32:31 +0200 Subject: [PATCH] Use ImmutableNodes.fromInstanceId in netconf Build normalized node strcuture from Yang Instance Id using new utilities from yang-data-impl. Change-Id: I1862d17e2356b965d4875ce5e715891cf94b17fb Signed-off-by: Maros Marsalek --- .../mdsal/src/main/resources/features.xml | 4 - .../netconf/util/InstanceIdToNodes.java | 596 ------------------ .../connect/netconf/util/NetconfBaseOps.java | 3 +- .../util/NetconfMessageTransformUtil.java | 12 +- .../netconf/util/NodeContainerProxy.java | 7 +- .../netconf/util/InstanceIdToNodesTest.java | 168 ----- .../test/resources/schemas/filter-test.yang | 74 --- .../osgi/YangStoreService.java | 9 +- .../netconf/mdsal-netconf-connector/pom.xml | 7 - .../mdsal/connector/ops/get/AbstractGet.java | 4 +- 10 files changed, 21 insertions(+), 863 deletions(-) delete mode 100644 opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodes.java delete mode 100644 opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodesTest.java delete mode 100644 opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/filter-test.yang diff --git a/features/mdsal/src/main/resources/features.xml b/features/mdsal/src/main/resources/features.xml index f8bbfeca49..a992d2f95e 100644 --- a/features/mdsal/src/main/resources/features.xml +++ b/features/mdsal/src/main/resources/features.xml @@ -27,10 +27,6 @@ odl-config-all odl-netconf-all - - odl-yangtools-models - mvn:org.opendaylight.controller/sal-netconf-connector/${project.version} - mvn:org.opendaylight.controller.model/model-inventory/${project.version} mvn:org.opendaylight.controller/netconf-ssh/${netconf.version} odl-mdsal-broker mvn:org.opendaylight.controller/mdsal-netconf-connector/${netconf.version} diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodes.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodes.java deleted file mode 100644 index d0b9efc8c0..0000000000 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodes.java +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Copyright (c) 2015 Cisco Systems, Inc. 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.controller.sal.connect.netconf.util; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import javax.xml.transform.dom.DOMSource; -import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; -import org.opendaylight.yangtools.concepts.Identifiable; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.ModifyAction; -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.NodeWithValue; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; -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.NormalizedNode; -import org.opendaylight.yangtools.yang.data.impl.schema.Builders; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.AttributesBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder; -import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; -import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; -import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; -import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; -import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; -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.LeafListSchemaNode; -import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; -import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; - -/** - * Transforms an instance of yang instance identifier to a filter like structure in normalized node format. Can be also used to nest the edit-config rpc content. - * For each argument of the id, a specific normalized node is created to ensure schema context conformance. - */ -public abstract class InstanceIdToNodes implements Identifiable { - - private final T identifier; - - @Override - public T getIdentifier() { - return identifier; - } - - protected InstanceIdToNodes(final T identifier) { - this.identifier = identifier; - } - - abstract InstanceIdToNodes getChild(final PathArgument child) throws DataNormalizationException; - - public abstract NormalizedNode create(YangInstanceIdentifier legacyData, Optional> deepestChild, Optional operation); - - private static abstract class SimpleTypeNormalization extends InstanceIdToNodes { - - protected SimpleTypeNormalization(final T identifier) { - super(identifier); - } - - @Override - public NormalizedNode create(final YangInstanceIdentifier id, final Optional> deepestChild, final Optional operation) { - checkNotNull(id); - final PathArgument pathArgument = Iterables.get(id.getPathArguments(), 0); - final NormalizedNodeAttrBuilder> builder = getBuilder(pathArgument); - - if(deepestChild.isPresent()) { - builder.withValue(deepestChild.get().getValue()); - } - - addModifyOpIfPresent(operation, builder); - return builder.build(); - } - - protected abstract NormalizedNodeAttrBuilder> getBuilder(PathArgument node); - - @Override - public InstanceIdToNodes getChild(final PathArgument child) { - return null; - } - } - - - public void addModifyOpIfPresent(final Optional operation, final AttributesBuilder builder) { - if(operation.isPresent()) { - builder.withAttributes(Collections.singletonMap(NetconfMessageTransformUtil.NETCONF_OPERATION_QNAME, NetconfMessageTransformUtil.modifyOperationToXmlString(operation.get()))); - } - } - - private static final class LeafNormalization extends SimpleTypeNormalization { - - protected LeafNormalization(final LeafSchemaNode potential) { - super(new NodeIdentifier(potential.getQName())); - } - - @Override - protected NormalizedNodeAttrBuilder> getBuilder(final PathArgument node) { - return Builders.leafBuilder().withNodeIdentifier(getIdentifier()); - } - } - - private static final class LeafListEntryNormalization extends SimpleTypeNormalization { - - public LeafListEntryNormalization(final LeafListSchemaNode potential) { - super(new NodeWithValue(potential.getQName(), null)); - } - - @Override - protected NormalizedNodeAttrBuilder> getBuilder(final PathArgument node) { - Preconditions.checkArgument(node instanceof NodeWithValue); - return Builders.leafSetEntryBuilder().withNodeIdentifier((NodeWithValue) node).withValue(((NodeWithValue) node).getValue()); - } - - } - - private static abstract class CompositeNodeNormalizationOperation extends - InstanceIdToNodes { - - protected CompositeNodeNormalizationOperation(final T identifier) { - super(identifier); - } - - @Override - @SuppressWarnings("unchecked") - public final NormalizedNode create(final YangInstanceIdentifier id, final Optional> lastChild, final Optional operation) { - checkNotNull(id); - final Iterator iterator = id.getPathArguments().iterator(); - final PathArgument legacyData = iterator.next(); - - if (!isMixin(this) && getIdentifier().getNodeType() != null) { - checkArgument(getIdentifier().getNodeType().equals(legacyData.getNodeType()), - "Node QName must be %s was %s", getIdentifier().getNodeType(), legacyData.getNodeType()); - } - final NormalizedNodeContainerBuilder builder = createBuilder(legacyData); - - if (iterator.hasNext()) { - final PathArgument childPath = iterator.next(); - final InstanceIdToNodes childOp = getChildOperation(childPath); - - final YangInstanceIdentifier childId = YangInstanceIdentifier.create(Iterables.skip(id.getPathArguments(), 1)); - builder.addChild(childOp.create(childId, lastChild, operation)); - } else { - if(lastChild.isPresent()) { - builder.withValue(Lists.newArrayList((Collection) lastChild.get().getValue())); - } - if(operation.isPresent()) { - Preconditions.checkArgument(builder instanceof AttributesBuilder); - addModifyOpIfPresent(operation, ((AttributesBuilder) builder)); - } - } - - return builder.build(); - } - - private InstanceIdToNodes getChildOperation(final PathArgument childPath) { - final InstanceIdToNodes childOp; - try { - childOp = getChild(childPath); - } catch (final DataNormalizationException e) { - throw new IllegalArgumentException(String.format("Failed to process child node %s", childPath), e); - } - checkArgument(childOp != null, "Node %s is not allowed inside %s", childPath, getIdentifier()); - return childOp; - } - - @SuppressWarnings("rawtypes") - protected abstract NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode); - } - - static boolean isMixin(final InstanceIdToNodes op) { - return op instanceof MixinNormalizationOp; - } - - private static abstract class DataContainerNormalizationOperation extends - CompositeNodeNormalizationOperation { - - private final DataNodeContainer schema; - private final Map> byArg; - - protected DataContainerNormalizationOperation(final T identifier, final DataNodeContainer schema) { - super(identifier); - this.schema = schema; - this.byArg = new ConcurrentHashMap<>(); - } - - @Override - public InstanceIdToNodes getChild(final PathArgument child) throws DataNormalizationException { - InstanceIdToNodes potential = byArg.get(child); - if (potential != null) { - return potential; - } - potential = fromLocalSchema(child); - return register(potential); - } - - private InstanceIdToNodes fromLocalSchema(final PathArgument child) throws DataNormalizationException { - if (child instanceof AugmentationIdentifier) { - return fromSchemaAndQNameChecked(schema, ((AugmentationIdentifier) child).getPossibleChildNames() - .iterator().next()); - } - return fromSchemaAndQNameChecked(schema, child.getNodeType()); - } - - private InstanceIdToNodes register(final InstanceIdToNodes potential) { - if (potential != null) { - byArg.put(potential.getIdentifier(), potential); - } - return potential; - } - } - - private static final class ListItemNormalization extends - DataContainerNormalizationOperation { - - protected ListItemNormalization(final NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) { - super(identifier, schema); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument currentArg) { - final DataContainerNodeAttrBuilder builder = Builders - .mapEntryBuilder().withNodeIdentifier((NodeIdentifierWithPredicates) currentArg); - for (final Entry keyValue : ((NodeIdentifierWithPredicates) currentArg).getKeyValues().entrySet()) { - builder.addChild(Builders.leafBuilder() - // - .withNodeIdentifier(new NodeIdentifier(keyValue.getKey())).withValue(keyValue.getValue()) - .build()); - } - return builder; - } - - } - - private static final class UnkeyedListItemNormalization extends DataContainerNormalizationOperation { - - protected UnkeyedListItemNormalization(final ListSchemaNode schema) { - super(new NodeIdentifier(schema.getQName()), schema); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.unkeyedListEntryBuilder().withNodeIdentifier(getIdentifier()); - } - - } - - private static final class ContainerTransformation extends DataContainerNormalizationOperation { - - protected ContainerTransformation(final ContainerSchemaNode schema) { - super(new NodeIdentifier(schema.getQName()), schema); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.containerBuilder().withNodeIdentifier(getIdentifier()); - } - } - - /** - * Marker interface for Mixin nodes normalization operations - */ - private interface MixinNormalizationOp {} - - - private static final class OrderedLeafListMixinNormalization extends UnorderedLeafListMixinNormalization { - - - public OrderedLeafListMixinNormalization(final LeafListSchemaNode potential) { - super(potential); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.orderedLeafSetBuilder().withNodeIdentifier(getIdentifier()); - } - } - - private static class UnorderedLeafListMixinNormalization extends CompositeNodeNormalizationOperation implements MixinNormalizationOp { - - private final InstanceIdToNodes innerOp; - - public UnorderedLeafListMixinNormalization(final LeafListSchemaNode potential) { - super(new NodeIdentifier(potential.getQName())); - innerOp = new LeafListEntryNormalization(potential); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.leafSetBuilder().withNodeIdentifier(getIdentifier()); - } - - @Override - public InstanceIdToNodes getChild(final PathArgument child) { - if (child instanceof NodeWithValue) { - return innerOp; - } - return null; - } - } - - private static final class AugmentationNormalization extends DataContainerNormalizationOperation implements MixinNormalizationOp { - - public AugmentationNormalization(final AugmentationSchema augmentation, final DataNodeContainer schema) { - //super(); - super(augmentationIdentifierFrom(augmentation), augmentationProxy(augmentation, schema)); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.augmentationBuilder().withNodeIdentifier(getIdentifier()); - } - } - - private static class UnorderedMapMixinNormalization extends CompositeNodeNormalizationOperation implements MixinNormalizationOp { - - private final ListItemNormalization innerNode; - - public UnorderedMapMixinNormalization(final ListSchemaNode list) { - super(new NodeIdentifier(list.getQName())); - this.innerNode = new ListItemNormalization(new NodeIdentifierWithPredicates(list.getQName(), - Collections.emptyMap()), list); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.mapBuilder().withNodeIdentifier(getIdentifier()); - } - - @Override - public InstanceIdToNodes getChild(final PathArgument child) { - if (child.getNodeType().equals(getIdentifier().getNodeType())) { - return innerNode; - } - return null; - } - } - - private static class UnkeyedListMixinNormalization extends CompositeNodeNormalizationOperation implements MixinNormalizationOp { - - private final UnkeyedListItemNormalization innerNode; - - public UnkeyedListMixinNormalization(final ListSchemaNode list) { - super(new NodeIdentifier(list.getQName())); - this.innerNode = new UnkeyedListItemNormalization(list); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.unkeyedListBuilder().withNodeIdentifier(getIdentifier()); - } - - @Override - public InstanceIdToNodes getChild(final PathArgument child) { - if (child.getNodeType().equals(getIdentifier().getNodeType())) { - return innerNode; - } - return null; - } - - } - - private static final class OrderedMapMixinNormalization extends UnorderedMapMixinNormalization { - - public OrderedMapMixinNormalization(final ListSchemaNode list) { - super(list); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.orderedMapBuilder().withNodeIdentifier(getIdentifier()); - } - - } - - private static class ChoiceNodeNormalization extends CompositeNodeNormalizationOperation implements MixinNormalizationOp { - - private final ImmutableMap> byArg; - - protected ChoiceNodeNormalization(final ChoiceSchemaNode schema) { - super(new NodeIdentifier(schema.getQName())); - final ImmutableMap.Builder> byArgBuilder = ImmutableMap.builder(); - - for (final ChoiceCaseNode caze : schema.getCases()) { - for (final DataSchemaNode cazeChild : caze.getChildNodes()) { - final InstanceIdToNodes childOp = fromDataSchemaNode(cazeChild); - byArgBuilder.put(childOp.getIdentifier(), childOp); - } - } - byArg = byArgBuilder.build(); - } - - @Override - public InstanceIdToNodes getChild(final PathArgument child) { - return byArg.get(child); - } - - @Override - protected NormalizedNodeContainerBuilder createBuilder(final PathArgument compositeNode) { - return Builders.choiceBuilder().withNodeIdentifier(getIdentifier()); - } - } - - private static class AnyXmlNormalization extends InstanceIdToNodes { - - protected AnyXmlNormalization(final AnyXmlSchemaNode schema) { - super(new NodeIdentifier(schema.getQName())); - } - - @Override - public InstanceIdToNodes getChild(final PathArgument child) throws DataNormalizationException { - return null; - } - - @Override - public NormalizedNode create(final YangInstanceIdentifier legacyData, final Optional> deepestChild, final Optional operation) { - if(deepestChild.isPresent()) { - Preconditions.checkState(deepestChild instanceof AnyXmlNode); - final NormalizedNodeAttrBuilder anyXmlBuilder = - Builders.anyXmlBuilder().withNodeIdentifier(getIdentifier()).withValue(((AnyXmlNode) deepestChild).getValue()); - addModifyOpIfPresent(operation, anyXmlBuilder); - return anyXmlBuilder.build(); - } - - final NormalizedNodeAttrBuilder builder = - Builders.anyXmlBuilder().withNodeIdentifier(getIdentifier()); - addModifyOpIfPresent(operation, builder); - return builder.build(); - } - - } - - private static Optional findChildSchemaNode(final DataNodeContainer parent, final QName child) { - DataSchemaNode potential = parent.getDataChildByName(child); - if (potential == null) { - final Iterable choices = FluentIterable.from(parent.getChildNodes()).filter(ChoiceSchemaNode.class); - potential = findChoice(choices, child); - } - return Optional.fromNullable(potential); - } - - private static InstanceIdToNodes fromSchemaAndQNameChecked(final DataNodeContainer schema, final QName child) throws DataNormalizationException { - final Optional potential = findChildSchemaNode(schema, child); - if (!potential.isPresent()) { - throw new DataNormalizationException(String.format("Supplied QName %s is not valid according to schema %s, potential children nodes: %s", child, schema, schema.getChildNodes())); - } - - final DataSchemaNode result = potential.get(); - // We try to look up if this node was added by augmentation - if ((schema instanceof DataSchemaNode) && result.isAugmenting()) { - return fromAugmentation(schema, (AugmentationTarget) schema, result); - } - return fromDataSchemaNode(result); - } - - private static ChoiceSchemaNode findChoice(final Iterable choices, final QName child) { - org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode foundChoice = null; - choiceLoop: - for (final ChoiceSchemaNode choice : choices) { - for (final ChoiceCaseNode caze : choice.getCases()) { - if (findChildSchemaNode(caze, child).isPresent()) { - foundChoice = choice; - break choiceLoop; - } - } - } - return foundChoice; - } - - private static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) { - final ImmutableSet.Builder potentialChildren = ImmutableSet.builder(); - for (final DataSchemaNode child : augmentation.getChildNodes()) { - potentialChildren.add(child.getQName()); - } - return new AugmentationIdentifier(potentialChildren.build()); - } - - private static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation, final DataNodeContainer schema) { - final Set children = new HashSet<>(); - for (final DataSchemaNode augNode : augmentation.getChildNodes()) { - children.add(schema.getDataChildByName(augNode.getQName())); - } - return new NodeContainerProxy(null, children); - } - - /** - * Returns a SchemaPathUtil for provided child node - *

- * If supplied child is added by Augmentation this operation returns - * a SchemaPathUtil for augmentation, - * otherwise returns a SchemaPathUtil for child as - * call for {@link #fromDataSchemaNode(org.opendaylight.yangtools.yang.model.api.DataSchemaNode)}. - */ - private static InstanceIdToNodes fromAugmentation(final DataNodeContainer parent, - final AugmentationTarget parentAug, final DataSchemaNode child) { - AugmentationSchema augmentation = null; - for (final AugmentationSchema aug : parentAug.getAvailableAugmentations()) { - final DataSchemaNode potential = aug.getDataChildByName(child.getQName()); - if (potential != null) { - augmentation = aug; - break; - } - - } - if (augmentation != null) { - return new AugmentationNormalization(augmentation, parent); - } else { - return fromDataSchemaNode(child); - } - } - - private static InstanceIdToNodes fromDataSchemaNode(final DataSchemaNode potential) { - if (potential instanceof ContainerSchemaNode) { - return new ContainerTransformation((ContainerSchemaNode) potential); - } else if (potential instanceof ListSchemaNode) { - return fromListSchemaNode((ListSchemaNode) potential); - } else if (potential instanceof LeafSchemaNode) { - return new LeafNormalization((LeafSchemaNode) potential); - } else if (potential instanceof ChoiceSchemaNode) { - return new ChoiceNodeNormalization((ChoiceSchemaNode) potential); - } else if (potential instanceof LeafListSchemaNode) { - return fromLeafListSchemaNode((LeafListSchemaNode) potential); - } else if (potential instanceof AnyXmlSchemaNode) { - return new AnyXmlNormalization((AnyXmlSchemaNode) potential); - } - return null; - } - - private static InstanceIdToNodes fromListSchemaNode(final ListSchemaNode potential) { - final List keyDefinition = potential.getKeyDefinition(); - if (keyDefinition == null || keyDefinition.isEmpty()) { - return new UnkeyedListMixinNormalization(potential); - } - if (potential.isUserOrdered()) { - return new OrderedMapMixinNormalization(potential); - } - return new UnorderedMapMixinNormalization(potential); - } - - private static InstanceIdToNodes fromLeafListSchemaNode(final LeafListSchemaNode potential) { - if (potential.isUserOrdered()) { - return new OrderedLeafListMixinNormalization(potential); - } - return new UnorderedLeafListMixinNormalization(potential); - } - - public static NormalizedNode serialize(final SchemaContext ctx, final YangInstanceIdentifier id) { - return serialize(ctx, id, Optional.>absent(), Optional.absent()); - } - - public static NormalizedNode serialize(final SchemaContext ctx, final YangInstanceIdentifier id, final NormalizedNode deepestElement) { - return serialize(ctx, id, Optional.>of(deepestElement), Optional.absent()); - } - - public static NormalizedNode serialize(final SchemaContext ctx, final YangInstanceIdentifier id, final Optional> deepestElement, final Optional operation) { - Preconditions.checkNotNull(ctx); - Preconditions.checkNotNull(id); - final PathArgument topLevelElement = id.getPathArguments().iterator().next(); - final DataSchemaNode dataChildByName = ctx.getDataChildByName(topLevelElement.getNodeType()); - Preconditions.checkNotNull(dataChildByName, "Cannot find %s node in schema context. Instance identifier has to start from root", topLevelElement); - try { - final InstanceIdToNodes instanceIdToNodes = fromSchemaAndQNameChecked(ctx, topLevelElement.getNodeType()); - return instanceIdToNodes.create(id, deepestElement, operation); - } catch (final DataNormalizationException e) { - throw new IllegalArgumentException("Unable to serialize: " + id, e); - } - } -} diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java index c19bb48408..bf432d3860 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java @@ -235,7 +235,8 @@ public final class NetconfBaseOps { // Default operation if(defaultOperation.isPresent()) { - editBuilder.withChild(Builders.leafBuilder().withNodeIdentifier(toId(NETCONF_DEFAULT_OPERATION_QNAME)).withValue(NetconfMessageTransformUtil.modifyOperationToXmlString(defaultOperation.get())).build()); + final String opString = defaultOperation.get().name().toLowerCase(); + editBuilder.withChild(Builders.leafBuilder().withNodeIdentifier(toId(NETCONF_DEFAULT_OPERATION_QNAME)).withValue(opString).build()); } // Error option diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java index dc1c8c7c40..1da39cf751 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java @@ -14,6 +14,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import java.io.IOException; import java.net.URI; +import java.util.AbstractMap; import java.util.Collections; import java.util.Map; import java.util.Map.Entry; @@ -44,6 +45,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStre import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; @@ -145,7 +147,7 @@ public class NetconfMessageTransformUtil { final NormalizedNodeAttrBuilder anyXmlBuilder = Builders.anyXmlBuilder().withNodeIdentifier(toId(NETCONF_FILTER_QNAME)); anyXmlBuilder.withAttributes(Collections.singletonMap(NETCONF_TYPE_QNAME, SUBTREE)); - final NormalizedNode filterContent = InstanceIdToNodes.serialize(ctx, identifier); + final NormalizedNode filterContent = ImmutableNodes.fromInstanceId(ctx, identifier); final Element element = XmlUtil.createElement(BLANK_DOCUMENT, NETCONF_FILTER_QNAME.getLocalName(), Optional.of(NETCONF_FILTER_QNAME.getNamespace().toString())); element.setAttributeNS(NETCONF_FILTER_QNAME.getNamespace().toString(), NETCONF_TYPE_QNAME.getLocalName(), "subtree"); @@ -268,7 +270,9 @@ public class NetconfMessageTransformUtil { "Data has to be either container or a list node when creating structure for top level element, but was: %s", lastChildOverride.get()); configContent = lastChildOverride.get(); } else { - configContent = InstanceIdToNodes.serialize(ctx, dataPath, lastChildOverride, operation); + final Entry modifyOperation = + operation.isPresent() ? new AbstractMap.SimpleEntry<>(NETCONF_OPERATION_QNAME, operation.get()) : null; + configContent = ImmutableNodes.fromInstanceId(ctx, dataPath, lastChildOverride, Optional.fromNullable(modifyOperation)); } final Element element = XmlUtil.createElement(BLANK_DOCUMENT, NETCONF_CONFIG_QNAME.getLocalName(), Optional.of(NETCONF_CONFIG_QNAME.getNamespace().toString())); @@ -287,10 +291,6 @@ public class NetconfMessageTransformUtil { return SchemaPath.create(true, rpc); } - public static String modifyOperationToXmlString(final ModifyAction operation) { - return operation.name().toLowerCase(); - } - // FIXME similar code is in netconf-notifications-impl , DRY public static void writeNormalizedNode(final NormalizedNode normalized, final DOMResult result, final SchemaPath schemaPath, final SchemaContext context) throws IOException, XMLStreamException { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NodeContainerProxy.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NodeContainerProxy.java index b499bd8f6f..23e2137026 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NodeContainerProxy.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NodeContainerProxy.java @@ -28,7 +28,10 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; import org.opendaylight.yangtools.yang.model.api.UsesNode; -class NodeContainerProxy implements ContainerSchemaNode { +/** + * Simple proxy for container like schema nodes, where user provides a collection of children schema nodes + */ +public final class NodeContainerProxy implements ContainerSchemaNode { private final Map childNodes; private final QName qName; @@ -146,4 +149,4 @@ class NodeContainerProxy implements ContainerSchemaNode { public List getUnknownSchemaNodes() { return Collections.emptyList(); } -} +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodesTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodesTest.java deleted file mode 100644 index 39a8f42f49..0000000000 --- a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/util/InstanceIdToNodesTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2015 Cisco Systems, Inc. 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.controller.sal.connect.netconf.util; - -import static org.junit.Assert.assertEquals; - -import com.google.common.base.Function; -import com.google.common.collect.Collections2; -import com.google.common.io.ByteSource; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; -import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; -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.impl.schema.Builders; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException; -import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; - -public class InstanceIdToNodesTest { - - private static final String NS = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:normalization:test"; - private static final String REVISION = "2014-03-13"; - private static final QName ID = QName.create(NS, REVISION, "id"); - private SchemaContext ctx; - - private final YangInstanceIdentifier.NodeIdentifier rootContainer = new YangInstanceIdentifier.NodeIdentifier(QName.create(NS, REVISION, "test")); - private final YangInstanceIdentifier.NodeIdentifier outerContainer = new YangInstanceIdentifier.NodeIdentifier(QName.create(NS, REVISION, "outer-container")); - private final YangInstanceIdentifier.NodeIdentifier augmentedLeaf = new YangInstanceIdentifier.NodeIdentifier(QName.create(NS, REVISION, "augmented-leaf")); - private final YangInstanceIdentifier.AugmentationIdentifier augmentation = new YangInstanceIdentifier.AugmentationIdentifier(Collections.singleton(augmentedLeaf.getNodeType())); - - private final YangInstanceIdentifier.NodeIdentifier outerList = new YangInstanceIdentifier.NodeIdentifier(QName.create(NS, REVISION, "outer-list")); - private final YangInstanceIdentifier.NodeIdentifierWithPredicates outerListWithKey = new YangInstanceIdentifier.NodeIdentifierWithPredicates(QName.create(NS, REVISION, "outer-list"), ID, 1); - private final YangInstanceIdentifier.NodeIdentifier choice = new YangInstanceIdentifier.NodeIdentifier(QName.create(NS, REVISION, "outer-choice")); - private final YangInstanceIdentifier.NodeIdentifier leafFromCase = new YangInstanceIdentifier.NodeIdentifier(QName.create(NS, REVISION, "one")); - - private final YangInstanceIdentifier.NodeIdentifier leafList = new YangInstanceIdentifier.NodeIdentifier(QName.create(NS, REVISION, "ordered-leaf-list")); - private final YangInstanceIdentifier.NodeWithValue leafListWithValue = new YangInstanceIdentifier.NodeWithValue(leafList.getNodeType(), "abcd"); - - static SchemaContext createTestContext() throws IOException, YangSyntaxErrorException { - final YangParserImpl parser = new YangParserImpl(); - return parser.parseSources(Collections2.transform(Collections.singletonList("/schemas/filter-test.yang"), new Function() { - @Override - public ByteSource apply(final String input) { - return new ByteSource() { - @Override - public InputStream openStream() throws IOException { - return InstanceIdToNodesTest.class.getResourceAsStream(input); - } - }; - } - })); - } - - @Before - public void setUp() throws Exception { - ctx = createTestContext(); - - } - - @Test - public void testInAugment() throws Exception { - final ContainerNode expectedFilter = Builders.containerBuilder().withNodeIdentifier(rootContainer).withChild( - Builders.containerBuilder().withNodeIdentifier(outerContainer).withChild( - Builders.augmentationBuilder().withNodeIdentifier(augmentation).withChild( - Builders.leafBuilder().withNodeIdentifier(augmentedLeaf).build() - ).build() - ).build() - ).build(); - - final NormalizedNode filter = InstanceIdToNodes.serialize(ctx, YangInstanceIdentifier.create(rootContainer, outerContainer, augmentation, augmentedLeaf)); - assertEquals(expectedFilter, filter); - } - - @Test - public void testInAugmentLeafOverride() throws Exception { - final LeafNode lastLeaf = Builders.leafBuilder().withNodeIdentifier(augmentedLeaf).withValue("randomValue").build(); - - final ContainerNode expectedFilter = Builders.containerBuilder().withNodeIdentifier(rootContainer).withChild( - Builders.containerBuilder().withNodeIdentifier(outerContainer).withChild( - Builders.augmentationBuilder().withNodeIdentifier(augmentation).withChild( - lastLeaf - ).build() - ).build() - ).build(); - - final NormalizedNode filter = InstanceIdToNodes.serialize(ctx, YangInstanceIdentifier.create(rootContainer, outerContainer, augmentation, augmentedLeaf), lastLeaf); - assertEquals(expectedFilter, filter); - } - - @Test - public void testListChoice() throws Exception { - final ContainerNode expectedFilter = Builders.containerBuilder().withNodeIdentifier(rootContainer).withChild( - Builders.mapBuilder().withNodeIdentifier(outerList).withChild( - Builders.mapEntryBuilder().withNodeIdentifier(outerListWithKey).withChild( - Builders.leafBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(ID)).withValue(1).build() - ).withChild( - Builders.choiceBuilder().withNodeIdentifier(choice).withChild( - Builders.leafBuilder().withNodeIdentifier(leafFromCase).build() - ).build() - ).build() - ).build() - ).build(); - - final NormalizedNode filter = InstanceIdToNodes.serialize(ctx, YangInstanceIdentifier.create(rootContainer, outerList, outerListWithKey, choice, leafFromCase)); - assertEquals(expectedFilter, filter); - } - - @Test - public void testTopContainerLastChildOverride() throws Exception { - final ContainerNode expectedStructure = Builders.containerBuilder().withNodeIdentifier(rootContainer).withChild( - Builders.mapBuilder().withNodeIdentifier(outerList).withChild( - Builders.mapEntryBuilder().withNodeIdentifier(outerListWithKey).withChild( - Builders.leafBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(ID)).withValue(1).build() - ).withChild( - Builders.choiceBuilder().withNodeIdentifier(choice).withChild( - Builders.leafBuilder().withNodeIdentifier(leafFromCase).build() - ).build() - ).build() - ).build() - ).build(); - - final NormalizedNode filter = InstanceIdToNodes.serialize(ctx, YangInstanceIdentifier.create(rootContainer), expectedStructure); - assertEquals(expectedStructure, filter); - } - - @Test - public void testListLastChildOverride() throws Exception { - final MapEntryNode outerListEntry = Builders.mapEntryBuilder().withNodeIdentifier(outerListWithKey).withChild( - Builders.leafBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(ID)).withValue(1).build() - ).build(); - final MapNode lastChild = Builders.mapBuilder().withNodeIdentifier(this.outerList).withChild( - outerListEntry - ).build(); - final ContainerNode expectedStructure = Builders.containerBuilder().withNodeIdentifier(rootContainer).withChild( - lastChild - ).build(); - - NormalizedNode filter = InstanceIdToNodes.serialize(ctx, YangInstanceIdentifier.create(rootContainer, outerList, outerListWithKey), outerListEntry); - assertEquals(expectedStructure, filter); - filter = InstanceIdToNodes.serialize(ctx, YangInstanceIdentifier.create(rootContainer, outerList, outerListWithKey)); - assertEquals(expectedStructure, filter); - } - - @Test - public void testLeafList() throws Exception { - final ContainerNode expectedFilter = Builders.containerBuilder().withNodeIdentifier(rootContainer).withChild( - Builders.orderedLeafSetBuilder().withNodeIdentifier(leafList).withChild( - Builders.leafSetEntryBuilder().withNodeIdentifier(leafListWithValue).withValue(leafListWithValue.getValue()).build() - ).build() - ).build(); - - final NormalizedNode filter = InstanceIdToNodes.serialize(ctx, YangInstanceIdentifier.create(rootContainer, leafList, leafListWithValue)); - assertEquals(expectedFilter, filter); - } -} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/filter-test.yang b/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/filter-test.yang deleted file mode 100644 index 6df5306850..0000000000 --- a/opendaylight/md-sal/sal-netconf-connector/src/test/resources/schemas/filter-test.yang +++ /dev/null @@ -1,74 +0,0 @@ -module normalization-test { - yang-version 1; - namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:normalization:test"; - prefix "norm-test"; - - revision "2014-03-13" { - description "Initial revision."; - } - - grouping outer-grouping { - } - - container test { - list outer-list { - key id; - leaf id { - type uint16; - } - choice outer-choice { - case one { - leaf one { - type string; - } - } - case two-three { - leaf two { - type string; - } - leaf three { - type string; - } - } - } - list inner-list { - key name; - ordered-by user; - - leaf name { - type string; - } - leaf value { - type string; - } - } - } - - list unkeyed-list { - leaf name { - type string; - } - } - - leaf-list unordered-leaf-list { - type string; - } - - leaf-list ordered-leaf-list { - ordered-by user; - type string; - } - - container outer-container { - } - - anyxml any-xml-data; - } - - augment /norm-test:test/norm-test:outer-container { - - leaf augmented-leaf { - type string; - } - } -} \ No newline at end of file diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java index cb035161b4..2961662092 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java @@ -137,12 +137,15 @@ public class YangStoreService implements YangStoreContext { } public AutoCloseable registerCapabilityListener(final CapabilityListener listener) { - if(ref.get() == null || ref.get().get() == null) { - getYangStoreSnapshot(); + final SoftReference yangStoreSnapshotSoftReference = ref.get(); + + YangStoreContext ret = yangStoreSnapshotSoftReference != null ? yangStoreSnapshotSoftReference.get() : null; + if(ret == null) { + ret = getYangStoreSnapshot(); } this.listeners.add(listener); - listener.onCapabilitiesAdded(NetconfOperationServiceFactoryImpl.setupCapabilities(ref.get().get())); + listener.onCapabilitiesAdded(NetconfOperationServiceFactoryImpl.setupCapabilities(ret)); return new AutoCloseable() { @Override diff --git a/opendaylight/netconf/mdsal-netconf-connector/pom.xml b/opendaylight/netconf/mdsal-netconf-connector/pom.xml index 878c37846b..d58bd54ae5 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/pom.xml +++ b/opendaylight/netconf/mdsal-netconf-connector/pom.xml @@ -92,13 +92,6 @@ xmlunit test - - - org.opendaylight.controller - sal-netconf-connector - - diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java index 9a66ceb5bc..d028a89e36 100644 --- a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java @@ -31,7 +31,6 @@ import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext; import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore; import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlElement; -import org.opendaylight.controller.sal.connect.netconf.util.InstanceIdToNodes; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; @@ -42,6 +41,7 @@ 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.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; @@ -151,7 +151,7 @@ public abstract class AbstractGet extends AbstractSingletonNetconfOperation { protected Element serializeNodeWithParentStructure(Document document, YangInstanceIdentifier dataRoot, NormalizedNode node) { if (!dataRoot.equals(ROOT)) { return (Element) transformNormalizedNode(document, - InstanceIdToNodes.serialize(schemaContext.getCurrentContext(), dataRoot, node), + ImmutableNodes.fromInstanceId(schemaContext.getCurrentContext(), dataRoot, node), ROOT); } return (Element) transformNormalizedNode(document, node, ROOT); -- 2.36.6