<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
-
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-test-model</artifactId>
+ <scope>test</scope>
</dependency>
+
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
+ <dependency><groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
import java.util.Map;
import java.util.Map.Entry;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
/**
* Serialization service, which provides two-way serialization between
* Java Binding Data representation and NormalizedNode representation.
- *
*/
public interface BindingNormalizedNodeSerializer {
* @param binding Binding Instance Identifier
* @return DOM Instance Identifier
*/
- YangInstanceIdentifier toYangInstanceIdentifier(InstanceIdentifier<?> binding);
+ YangInstanceIdentifier toYangInstanceIdentifier(@Nonnull InstanceIdentifier<?> binding);
/**
* Translates supplied YANG Instance Identifier into Binding instance identifier.
*
* @param dom YANG Instance Identifier
- * @return Binding Instance Identifier
+ * @return Binding Instance Identifier, or null if the instance identifier is not
+ * representable.
*/
- InstanceIdentifier<?> fromYangInstanceIdentifier(YangInstanceIdentifier dom);
+ @Nullable InstanceIdentifier<?> fromYangInstanceIdentifier(@Nonnull YangInstanceIdentifier dom);
/**
* Translates supplied Binding Instance Identifier and data into NormalizedNode representation.
* @param data Data object representing data
* @return NormalizedNode representation
*/
- <T extends DataObject> Entry<YangInstanceIdentifier,NormalizedNode<?,?>> toNormalizedNode(InstanceIdentifier<T> path, T data);
+ <T extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?,?>> toNormalizedNode(InstanceIdentifier<T> path, T data);
/**
* Translates supplied YANG Instance Identifier and NormalizedNode into Binding data.
* @param data NormalizedNode representing data
* @return DOM Instance Identifier
*/
- Entry<InstanceIdentifier<?>,DataObject> fromNormalizedNode(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
+ @Nullable Entry<InstanceIdentifier<?>,DataObject> fromNormalizedNode(@Nonnull YangInstanceIdentifier path, NormalizedNode<?, ?> data);
/**
* Returns map view which contains translated set of entries to normalized nodes.
import java.lang.reflect.Type;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
class BindingCodecContext implements CodecContextFactory, Immutable {
-
+ private static final Logger LOG = LoggerFactory.getLogger(BindingCodecContext.class);
private static final String GETTER_PREFIX = "get";
+
private final SchemaRootCodecContext root;
private final BindingRuntimeContext context;
private final Codec<YangInstanceIdentifier, InstanceIdentifier<?>> instanceIdentifierCodec =
return context;
}
- public Codec<YangInstanceIdentifier, InstanceIdentifier<?>> getInstanceIdentifierCodec() {
+ Codec<YangInstanceIdentifier, InstanceIdentifier<?>> getInstanceIdentifierCodec() {
return instanceIdentifierCodec;
}
return currentNode;
}
- public NodeCodecContext getCodecContextNode(final YangInstanceIdentifier dom,
- final List<InstanceIdentifier.PathArgument> builder) {
+ /**
+ * Multi-purpose utility function. Traverse the codec tree, looking for
+ * the appropriate codec for the specified {@link YangInstanceIdentifier}.
+ * As a side-effect, gather all traversed binding {@link InstanceIdentifier.PathArgument}s
+ * into the supplied collection.
+ *
+ * @param dom {@link YangInstanceIdentifier} which is to be translated
+ * @param bindingArguments Collection for traversed path arguments
+ * @return Codec for target node, or @null if the node does not have a
+ * binding representation (choice, case, leaf).
+ */
+ @Nullable NodeCodecContext getCodecContextNode(final @Nonnull YangInstanceIdentifier dom,
+ final @Nonnull Collection<InstanceIdentifier.PathArgument> bindingArguments) {
NodeCodecContext currentNode = root;
ListNodeCodecContext currentList = null;
+
for (YangInstanceIdentifier.PathArgument domArg : dom.getPathArguments()) {
- Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?>);
- DataContainerCodecContext<?> previous = (DataContainerCodecContext<?>) currentNode;
- NodeCodecContext nextNode = previous.getYangIdentifierChild(domArg);
+ Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?>, "Unexpected child of non-container node %s", currentNode);
+ final DataContainerCodecContext<?> previous = (DataContainerCodecContext<?>) currentNode;
+ final NodeCodecContext nextNode = previous.getYangIdentifierChild(domArg);
+
/*
* List representation in YANG Instance Identifier consists of two
* arguments: first is list as a whole, second is list as an item so
* Identifier as Item or IdentifiableItem
*/
if (currentList != null) {
+ Preconditions.checkArgument(currentList == nextNode, "List should be referenced two times in YANG Instance Identifier %s", dom);
- if (currentList == nextNode) {
-
- // We entered list, so now we have all information to emit
- // list
- // path using second list argument.
- builder.add(currentList.getBindingPathArgument(domArg));
- currentList = null;
- currentNode = nextNode;
- } else {
- throw new IllegalArgumentException(
- "List should be referenced two times in YANG Instance Identifier");
- }
+ // We entered list, so now we have all information to emit
+ // list path using second list argument.
+ bindingArguments.add(currentList.getBindingPathArgument(domArg));
+ currentList = null;
+ currentNode = nextNode;
} else if (nextNode instanceof ListNodeCodecContext) {
// We enter list, we do not update current Node yet,
// since we need to verify
// it is not supported by binding instance identifier.
currentNode = nextNode;
} else if (nextNode instanceof DataContainerCodecContext<?>) {
- builder.add(((DataContainerCodecContext<?>) nextNode).getBindingPathArgument(domArg));
+ bindingArguments.add(((DataContainerCodecContext<?>) nextNode).getBindingPathArgument(domArg));
currentNode = nextNode;
} else if (nextNode instanceof LeafNodeCodecContext) {
- Preconditions.checkArgument(builder == null, "Instance Identifier for leaf is not representable.");
-
+ LOG.debug("Instance identifier referencing a leaf is not representable (%s)", dom);
+ return null;
}
}
+
// Algorithm ended in list as whole representation
// we sill need to emit identifier for list
-
- if (builder != null) {
- Preconditions.checkArgument(!(currentNode instanceof ChoiceNodeCodecContext),
- "Instance Identifier for choice is not representable.");
- Preconditions.checkArgument(!(currentNode instanceof CaseNodeCodecContext),
- "Instance Identifier for case is not representable.");
+ if (currentNode instanceof ChoiceNodeCodecContext) {
+ LOG.debug("Instance identifier targeting a choice is not representable (%s)", dom);
+ return null;
+ }
+ if (currentNode instanceof CaseNodeCodecContext) {
+ LOG.debug("Instance identifier targeting a case is not representable (%s)", dom);
+ return null;
}
+
if (currentList != null) {
- builder.add(currentList.getBindingPathArgument(null));
+ bindingArguments.add(currentList.getBindingPathArgument(null));
return currentList;
}
return currentNode;
} else if (rootType instanceof InstanceIdentifierTypeDefinition) {
return ValueTypeCodec.encapsulatedValueCodecFor(valueType, instanceIdentifierCodec);
} else if (rootType instanceof UnionTypeDefinition) {
- Callable<UnionTypeCodec> loader = UnionTypeCodec.loader(valueType, (UnionTypeDefinition) rootType,
- getInstanceIdentifierCodec(), getIdentityCodec());
+ Callable<UnionTypeCodec> loader = UnionTypeCodec.loader(valueType, (UnionTypeDefinition) rootType);
try {
return loader.call();
} catch (Exception e) {
- throw new IllegalStateException("Unable to load codec for "+valueType,e);
+ throw new IllegalStateException("Unable to load codec for " + valueType, e);
}
}
return ValueTypeCodec.getCodecFor(valueType, instantiatedType);
@Override
public YangInstanceIdentifier serialize(final InstanceIdentifier<?> input) {
- List<YangInstanceIdentifier.PathArgument> domArgs = new LinkedList<>();
+ List<YangInstanceIdentifier.PathArgument> domArgs = new ArrayList<>();
getCodecContextNode(input, domArgs);
return YangInstanceIdentifier.create(domArgs);
}
@Override
public InstanceIdentifier<?> deserialize(final YangInstanceIdentifier input) {
- List<InstanceIdentifier.PathArgument> builder = new LinkedList<>();
- getCodecContextNode(input, builder);
- return InstanceIdentifier.create(builder);
+ final List<InstanceIdentifier.PathArgument> builder = new ArrayList<>();
+ final NodeCodecContext codec = getCodecContextNode(input, builder);
+ return codec == null ? null : InstanceIdentifier.create(builder);
}
}
import java.io.IOException;
import java.util.AbstractMap.SimpleEntry;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
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.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@Override
public YangInstanceIdentifier toYangInstanceIdentifier(final InstanceIdentifier<?> binding) {
- List<YangInstanceIdentifier.PathArgument> builder = new LinkedList<>();
- codecContext.getCodecContextNode(binding, builder);
return codecContext.getInstanceIdentifierCodec().serialize(binding);
}
@Override
public InstanceIdentifier<?> fromYangInstanceIdentifier(final YangInstanceIdentifier dom) {
return codecContext.getInstanceIdentifierCodec().deserialize(dom);
- }
+ }
@Override
public <T extends DataObject> Entry<YangInstanceIdentifier,NormalizedNode<?,?>> toNormalizedNode(final InstanceIdentifier<T> path, final T data) {
NormalizedNodeResult result = new NormalizedNodeResult();
- // We create dom stream writer which produces normalized nodes
+ // We create DOM stream writer which produces normalized nodes
NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
- // We create Binding Stream Writer wchich translates from Binding to Normalized Nodes
+ // We create Binding Stream Writer which translates from Binding to Normalized Nodes
Entry<YangInstanceIdentifier, BindingStreamEventWriter> writeCtx = codecContext.newWriter(path, domWriter);
// We get serializer which reads binding data and uses Binding To Normalized Node writer to write result
return new SimpleEntry<YangInstanceIdentifier,NormalizedNode<?,?>>(writeCtx.getKey(),result.getResult());
}
- private boolean isBindingRepresentable(final NormalizedNode<?, ?> data) {
- return !(data instanceof MapNode) && !(data instanceof UnkeyedListNode) && !(data instanceof LeafSetNode) && !(data instanceof LeafNode<?>);
- }
+ private static boolean isBindingRepresentable(final NormalizedNode<?, ?> data) {
+ if (data instanceof ChoiceNode) {
+ return false;
+ }
+ if (data instanceof LeafNode<?>) {
+ return false;
+ }
+ if (data instanceof LeafSetNode) {
+ return false;
+ }
+ if( data instanceof LeafSetEntryNode<?>) {
+ return false;
+ }
+ if (data instanceof MapNode) {
+ return false;
+ }
+ if (data instanceof UnkeyedListNode) {
+ return false;
+ }
+ return true;
+ }
@Override
- public Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(final YangInstanceIdentifier path,
- final NormalizedNode<?, ?> data) {
- List<PathArgument> builder = new LinkedList<>();
- if(isBindingRepresentable(data)) {
- DataObject lazyObj = (DataObject) codecContext.getCodecContextNode(path, builder).dataFromNormalizedNode(data);
- InstanceIdentifier<?> bindingPath = InstanceIdentifier.create(builder);
- return new SimpleEntry<InstanceIdentifier<?>, DataObject>(bindingPath,lazyObj);
+ public Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+ if (!isBindingRepresentable(data)) {
+ return null;
}
- return null;
+
+ final List<PathArgument> builder = new ArrayList<>();
+ final NodeCodecContext codec = codecContext.getCodecContextNode(path, builder);
+ if (codec == null) {
+ if (data != null) {
+ LOG.warn("Path {} does not have a binding equivalent, should have been caught earlier ({})", path, data.getClass());
+ }
+ return null;
+ }
+
+ final DataObject lazyObj = (DataObject) codec.dataFromNormalizedNode(data);
+ final InstanceIdentifier<?> bindingPath = InstanceIdentifier.create(builder);
+ return new SimpleEntry<InstanceIdentifier<?>, DataObject>(bindingPath, lazyObj);
}
@Override
- public Map<InstanceIdentifier<?>, DataObject> fromNormalizedNodes(
- final Map<YangInstanceIdentifier, NormalizedNode<?, ?>> dom) {
+ public Map<InstanceIdentifier<?>, DataObject> fromNormalizedNodes(final Map<YangInstanceIdentifier, NormalizedNode<?, ?>> dom) {
throw new UnsupportedOperationException("Not implemented yet");
}
private static class DeserializeFunction<T> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
-
private final DataObjectCodecContext<?> ctx;
+
public DeserializeFunction(final DataObjectCodecContext<?> ctx) {
super();
this.ctx = ctx;
}
return Optional.absent();
}
-
-
}
private class GeneratorLoader extends CacheLoader<Class<? extends DataObject>, DataObjectSerializer> {
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
+
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder = new HashMap<>();
Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
-
+ Set<Class<?>> potentialSubstitutions = new HashSet<>();
+ // Walks all cases for supplied choice in current runtime context
for (Class<?> caze : factory().getRuntimeContext().getCases(bindingClass())) {
+ // We try to load case using exact match thus name
+ // and original schema must equals
DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
+ // If we have case definition, this case is instantiated
+ // at current location and thus is valid in context of parent choice
if (cazeDef != null) {
byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
+ // Updates collection of case children
for (Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses((Class) caze)) {
byCaseChildClassBuilder.put(cazeChild, cazeDef);
}
+ // Updates collection of YANG instance identifier to case
for (DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
byYangCaseChildBuilder.put(new NodeIdentifier(cazeChild.getQName()), cazeDef);
}
+ } else {
+ /*
+ * If case definition is not available, we store it for
+ * later check if it could be used as substitution of existing one.
+ */
+ potentialSubstitutions.add(caze);
}
}
+ Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
+ /*
+ * Walks all cases which are not directly instantiated and
+ * tries to match them to instantiated cases - represent same data as instantiated case,
+ * only case name or schema path is different. This is required due property of
+ * binding specification, that if choice is in grouping schema path location is lost,
+ * and users may use incorrect case class using copy builders.
+ */
+ for(Class<?> substitution : potentialSubstitutions) {
+ search: for(Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
+ if(BindingReflections.isSubstitutionFor(substitution, real.getKey())) {
+ bySubstitutionBuilder.put(substitution, real.getValue());
+ break search;
+ }
+ }
+ }
+ byClassBuilder.putAll(bySubstitutionBuilder);
byYangCaseChild = ImmutableMap.copyOf(byYangCaseChildBuilder);
byClass = ImmutableMap.copyOf(byClassBuilder);
byCaseChildClass = ImmutableMap.copyOf(byCaseChildClassBuilder);
@Override
protected DataContainerCodecContext<?> getStreamChild(final Class<?> childClass) {
DataContainerCodecPrototype<?> childProto = byStreamClass.get(childClass);
+ if (childProto != null) {
+ return childProto.get();
+ }
+
+ if (Augmentation.class.isAssignableFrom(childClass)) {
+ /*
+ * It is potentially mismatched valid augmentation - we look up equivalent augmentation
+ * using reflection and walk all stream child and compare augmenations classes
+ * if they are equivalent.
+ *
+ * FIXME: Cache mapping of mismatched augmentation to real one, to speed up lookup.
+ */
+ Class<?> augTarget = BindingReflections.findAugmentationTarget((Class) childClass);
+ if ((bindingClass().equals(augTarget))) {
+ for (DataContainerCodecPrototype<?> realChild : byStreamClass.values()) {
+ if (Augmentation.class.isAssignableFrom(realChild.getBindingClass())
+ && BindingReflections.isSubstitutionFor(childClass,realChild.getBindingClass())) {
+ childProto = realChild;
+ break;
+ }
+ }
+ }
+ }
Preconditions.checkArgument(childProto != null, " Child %s is not valid child.",childClass);
return childProto.get();
}
package org.opendaylight.yangtools.binding.data.codec.impl;
import com.google.common.collect.ImmutableSet;
+
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
-import org.opendaylight.yangtools.concepts.Codec;
+
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
}
}
- @SuppressWarnings("rawtypes")
- static final Callable<UnionTypeCodec> loader(final Class<?> unionCls,final UnionTypeDefinition unionType, final Codec instanceIdentifier, final Codec identity) {
+ static final Callable<UnionTypeCodec> loader(final Class<?> unionCls, final UnionTypeDefinition unionType) {
return new Callable<UnionTypeCodec>() {
-
@Override
- public UnionTypeCodec call() throws Exception {
+ public UnionTypeCodec call() throws NoSuchMethodException, SecurityException {
Set<UnionValueOptionContext> values = new HashSet<>();
for(TypeDefinition<?> subtype : unionType.getTypes()) {
String methodName = "get" + BindingMapping.getClassName(subtype.getQName());
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import org.junit.Before;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public abstract class AbstractBindingRuntimeTest {
+
+ private SchemaContext schemaContext;
+ private BindingRuntimeContext runtimeContext;
+
+ @Before
+ public void setup() {
+ ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
+ ctx.addModuleInfos(BindingReflections.loadModuleInfos());
+ schemaContext = ctx.tryToCreateSchemaContext().get();
+ runtimeContext = BindingRuntimeContext.create(ctx, schemaContext);
+
+ }
+
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ public BindingRuntimeContext getRuntimeContext() {
+ return runtimeContext;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class AugmentationSubstitutionTest extends AbstractBindingRuntimeTest {
+
+ private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+ private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+ .child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+ private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+ .augmentation(TreeLeafOnlyAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+ .augmentation(TreeComplexUsesAugment.class);
+ private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+ private BindingNormalizedNodeCodecRegistry registry;
+
+ @Override
+ public void setup() {
+ super.setup();
+ JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ @Test
+ public void augmentationInGroupingSubstituted() {
+ TopLevelList baRpc = new TopLevelListBuilder()
+ .setKey(TOP_FOO_KEY)
+ .addAugmentation(RpcComplexUsesAugment.class, new RpcComplexUsesAugmentBuilder(createComplexData()).build())
+ .build();
+ TopLevelList baTree = new TopLevelListBuilder()
+ .setKey(TOP_FOO_KEY)
+ .addAugmentation(TreeComplexUsesAugment.class, new TreeComplexUsesAugmentBuilder(createComplexData()).build())
+ .build();
+ NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
+ NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
+ assertEquals(domTreeEntry, domRpcEntry);
+ }
+
+ private RpcComplexUsesAugment createComplexData() {
+ return new RpcComplexUsesAugmentBuilder()
+ .setContainerWithUses(new ContainerWithUsesBuilder()
+ .setLeafFromGrouping("foo")
+ .build())
+ .setListViaUses(Collections.<ListViaUses>emptyList())
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.put.top.input.top.level.list.choice.in.list.ComplexViaUsesWithDifferentNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.top.level.list.choice.in.list.ComplexViaUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class CaseSubstitutionTest extends AbstractBindingRuntimeTest {
+
+ private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+ private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+ .child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+ private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+ .augmentation(TreeLeafOnlyAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+ .augmentation(TreeComplexUsesAugment.class);
+ private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+ private BindingNormalizedNodeCodecRegistry registry;
+
+ @Override
+ public void setup() {
+ super.setup();
+ JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ @Test
+ public void choiceInGroupingSubstituted() {
+ TopLevelList baRpc = new TopLevelListBuilder()
+ .setKey(TOP_FOO_KEY)
+ .setChoiceInList(new ComplexViaUsesWithDifferentNameBuilder(createComplexData()).build())
+ .build();
+ TopLevelList baTree = new TopLevelListBuilder()
+ .setKey(TOP_FOO_KEY)
+ .setChoiceInList(new ComplexViaUsesBuilder(createComplexData()).build())
+ .build();
+ NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
+ NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
+ assertEquals(domTreeEntry, domRpcEntry);
+ }
+
+ private RpcComplexUsesAugment createComplexData() {
+ return new RpcComplexUsesAugmentBuilder()
+ .setContainerWithUses(new ContainerWithUsesBuilder()
+ .setLeafFromGrouping("foo")
+ .build())
+ .setListViaUses(Collections.<ListViaUses>emptyList())
+ .build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import com.google.common.collect.Iterables;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class InstanceIdentifierSerializeDeserializeTest extends AbstractBindingRuntimeTest{
+ public static final String TOP_LEVEL_LIST_KEY_VALUE = "foo";
+
+ private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+ private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+ .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+ private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+ BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES =
+ BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
+
+ public static final QName TOP_QNAME =
+ QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+ public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
+ public static final QName TOP_LEVEL_LIST_KEY = QName.create(TOP_QNAME, "name");
+ private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+ public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.builder().node(TOP_QNAME).build();
+ public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
+ public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_1_PATH = BI_TOP_LEVEL_LIST_PATH
+ .node(new YangInstanceIdentifier.NodeIdentifierWithPredicates(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY, TOP_LEVEL_LIST_KEY_VALUE));
+
+ private BindingNormalizedNodeCodecRegistry registry;
+
+ @Before
+ public void setup() {
+ super.setup();
+ JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ @Test
+ public void testYangIIToBindingAwareII() {
+ InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_PATH);
+ assertEquals(Top.class, instanceIdentifier.getTargetType());
+ }
+
+ @Test
+ public void testYangIIToBindingAwareIIListWildcarded() {
+ InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_PATH);
+ assertEquals(TopLevelList.class, instanceIdentifier.getTargetType());
+ assertTrue(instanceIdentifier.isWildcarded());
+ }
+
+ @Test
+ public void testYangIIToBindingAwareIIListWithKey() {
+ InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_1_PATH);
+ InstanceIdentifier.PathArgument last = Iterables.getLast(instanceIdentifier.getPathArguments());
+ assertEquals(TopLevelList.class, instanceIdentifier.getTargetType());
+ assertFalse(instanceIdentifier.isWildcarded());
+ assertTrue(last instanceof InstanceIdentifier.IdentifiableItem);
+ Identifier key = ((InstanceIdentifier.IdentifiableItem) last).getKey();
+ assertEquals(TopLevelListKey.class, key.getClass());
+ assertEquals(TOP_LEVEL_LIST_KEY_VALUE, ((TopLevelListKey)key).getName());
+ }
+
+ @Test
+ public void testBindingAwareIIToYangIContainer() {
+ YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+ InstanceIdentifier.create(Top.class).child(TopLevelList.class));
+ YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+ assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifier);
+ assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+ }
+
+ @Test
+ public void testBindingAwareIIToYangIIWildcard() {
+ YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+ InstanceIdentifier.create(Top.class).child(TopLevelList.class));
+ YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+ assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifier);
+ assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+ }
+
+ @Test
+ public void testBindingAwareIIToYangIIListWithKey() {
+ YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+ InstanceIdentifier.create(Top.class).child(TopLevelList.class, TOP_FOO_KEY));
+ YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+ assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates);
+ assertTrue(((YangInstanceIdentifier.NodeIdentifierWithPredicates) lastPathArgument).getKeyValues().containsValue(TOP_LEVEL_LIST_KEY_VALUE));
+ assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+ }
+
+ @Test
+ public void testBindingAwareIIToYangIIAugmentation() {
+ YangInstanceIdentifier.PathArgument lastArg = registry.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES).getLastPathArgument();
+ assertTrue(lastArg instanceof YangInstanceIdentifier.AugmentationIdentifier);
+ }
+
+ @Test
+ public void testBindingAwareIIToYangIILeafOnlyAugmentation() {
+ YangInstanceIdentifier.PathArgument leafOnlyLastArg = registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
+ assertTrue(leafOnlyLastArg instanceof YangInstanceIdentifier.AugmentationIdentifier);
+ assertTrue(((YangInstanceIdentifier.AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+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.PathArgument;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+public class InstanceIdentifierTest extends AbstractBindingRuntimeTest {
+
+ private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+ private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+ .child(TopLevelList.class, TOP_FOO_KEY).toInstance();
+ private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+ .augmentation(TreeLeafOnlyAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+ .augmentation(TreeComplexUsesAugment.class);
+ private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+ private BindingNormalizedNodeCodecRegistry registry;
+
+ @Override
+ public void setup() {
+ super.setup();
+ JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ @Test
+ public void testComplexAugmentationSerialization() {
+ YangInstanceIdentifier yangII = registry.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES);
+ PathArgument lastArg = yangII.getLastPathArgument();
+ assertTrue("Last argument should be AugmentationIdentifier", lastArg instanceof AugmentationIdentifier);
+ InstanceIdentifier<?> bindingII = registry.fromYangInstanceIdentifier(yangII);
+ assertEquals(BA_TREE_COMPLEX_USES, bindingII);
+ }
+
+ @Test
+ public void testLeafOnlyAugmentationSerialization() {
+ PathArgument leafOnlyLastArg = registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
+ assertTrue("Last argument should be AugmentationIdentifier", leafOnlyLastArg instanceof AugmentationIdentifier);
+ assertTrue(((AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.choice.identifier.ExtendedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.choice.identifier.extended.ExtendedIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+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.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.ImmutableLeafSetEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+
+public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingRuntimeTest{
+
+ public static final String TOP_LEVEL_LIST_FOO_KEY_VALUE = "foo";
+ public static final TopLevelListKey TOP_LEVEL_LIST_FOO_KEY = new TopLevelListKey(TOP_LEVEL_LIST_FOO_KEY_VALUE);
+
+ public static final QName TOP_QNAME =
+ QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+ public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
+ public static final QName TOP_LEVEL_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
+ public static final QName TOP_LEVEL_LEAF_LIST_QNAME = QName.create(TOP_QNAME, "top-level-leaf-list");
+ public static final QName NESTED_LIST_QNAME = QName.create(TOP_QNAME, "nested-list");
+ public static final QName NESTED_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
+ public static final QName CHOICE_CONTAINER_QNAME =
+ QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "choice-container");
+ public static final QName CHOICE_IDENTIFIER_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "identifier");
+ public static final QName CHOICE_IDENTIFIER_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "id");
+ public static final QName SIMPLE_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "simple-id");
+ public static final QName EXTENDED_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "extended-id");
+ private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+ private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+ .builder(Top.class).child(TopLevelList.class, TOP_LEVEL_LIST_FOO_KEY).toInstance();
+ private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+ BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES =
+ BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
+
+ public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.of(TOP_QNAME);
+ public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
+ public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_FOO_PATH = BI_TOP_LEVEL_LIST_PATH
+ .node(new YangInstanceIdentifier.NodeIdentifierWithPredicates(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE));
+ public static final YangInstanceIdentifier BI_CHOICE_CONTAINER_PATH = YangInstanceIdentifier.of(CHOICE_CONTAINER_QNAME);
+
+ private BindingNormalizedNodeCodecRegistry registry;
+
+ @Before
+ public void setup() {
+ super.setup();
+ JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+ registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+ registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+ }
+
+ @Test
+ public void containerToNormalized() {
+ Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+ registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top());
+ ContainerNode topNormalized = ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+ .withChild(mapNodeBuilder(TOP_LEVEL_LIST_QNAME).build()).build();
+ assertEquals(topNormalized, entry.getValue());
+ }
+
+ @Test
+ public void containerFromNormalized() {
+ ContainerNode topNormalized = ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+ .withChild(mapNodeBuilder(TOP_LEVEL_LIST_QNAME).build()).build();
+ Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_PATH, topNormalized);
+ assertEquals(top(), entry.getValue());
+ }
+
+ @Test
+ public void listWithKeysToNormalized() {
+ Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+ registry.toNormalizedNode(BA_TOP_LEVEL_LIST, topLevelList(TOP_LEVEL_LIST_FOO_KEY));
+ MapEntryNode topLevelListNormalized = ImmutableMapEntryNodeBuilder.create()
+ .withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+ TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .build();
+ assertEquals(topLevelListNormalized, entry.getValue());
+ }
+
+ @Test
+ public void listWithKeysFromNormalized() {
+ MapEntryNode topLevelListNormalized = ImmutableMapEntryNodeBuilder.create()
+ .withNodeIdentifier(
+ new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+ TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .build();
+ Map.Entry<InstanceIdentifier<?>, DataObject> entry =
+ registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH, topLevelListNormalized);
+ assertEquals(topLevelList(TOP_LEVEL_LIST_FOO_KEY), entry.getValue());
+ }
+
+ @Test
+ public void leafOnlyAugmentationToNormalized() {
+ Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+ registry.toNormalizedNode(BA_TREE_LEAF_ONLY, new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build());
+ Set<QName> augmentationChildren = new HashSet<>();
+ augmentationChildren.add(SIMPLE_VALUE_QNAME);
+ AugmentationNode augmentationNode = ImmutableAugmentationNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren))
+ .withChild(leafNode(SIMPLE_VALUE_QNAME, "simpleValue"))
+ .build();
+ assertEquals(augmentationNode, entry.getValue());
+ }
+
+ @Test
+ public void leafOnlyAugmentationFromNormalized() {
+ Set<QName> augmentationChildren = new HashSet<>();
+ augmentationChildren.add(SIMPLE_VALUE_QNAME);
+ AugmentationNode augmentationNode = ImmutableAugmentationNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren))
+ .withChild(leafNode(SIMPLE_VALUE_QNAME, "simpleValue"))
+ .build();
+ Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH.node(
+ new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren)), augmentationNode);
+ assertEquals(new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build(), entry.getValue());
+ }
+
+ @Test
+ public void leafListToNormalized() {
+ List<String> topLevelLeafList = new ArrayList<>();
+ topLevelLeafList.add("foo");
+ Top top = new TopBuilder().setTopLevelLeafList(topLevelLeafList).build();
+
+ Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+ registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top);
+ ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+ .withChild(ImmutableLeafSetNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
+ .withChild(
+ ImmutableLeafSetEntryNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue(TOP_LEVEL_LEAF_LIST_QNAME, "foo"))
+ .withValue("foo")
+ .build())
+ .build())
+ .build();
+ assertEquals(containerNode, entry.getValue());
+ }
+
+ @Test
+ public void leafListFromNormalized() {
+ ContainerNode topWithLeafList = ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+ .withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
+ .withChild(ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeWithValue(TOP_LEVEL_LEAF_LIST_QNAME, "foo")).withValue("foo").build()).build())
+ .build();
+ Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_PATH, topWithLeafList);
+ List<String> topLevelLeafList = new ArrayList<>();
+ topLevelLeafList.add("foo");
+ Top top = new TopBuilder().setTopLevelLeafList(topLevelLeafList).build();
+ assertEquals(top, entry.getValue());
+ }
+
+ @Test
+ public void choiceToNormalized() {
+ ChoiceContainer choiceContainerBA = new ChoiceContainerBuilder().setIdentifier(new ExtendedBuilder().setExtendedId(
+ new ExtendedIdBuilder().setId("identifier_value").build()).build()).build();
+ Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+ registry.toNormalizedNode(InstanceIdentifier.create(ChoiceContainer.class), choiceContainerBA);
+ ContainerNode choiceContainer = ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_CONTAINER_QNAME))
+ .withChild(ImmutableChoiceNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
+ .withChild(ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(EXTENDED_ID_QNAME))
+ .withChild(leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value")).build()).build())
+ .build();
+ assertEquals(choiceContainer, entry.getValue());
+ }
+
+ @Test
+ public void choiceFromNormalized() {
+ ContainerNode choiceContainerBI = ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_CONTAINER_QNAME))
+ .withChild(ImmutableChoiceNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
+ .withChild(ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(EXTENDED_ID_QNAME))
+ .withChild(leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value")).build()).build())
+ .build();
+ Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_CHOICE_CONTAINER_PATH, choiceContainerBI);
+ ChoiceContainer choiceContainerBA = new ChoiceContainerBuilder().setIdentifier(new ExtendedBuilder().setExtendedId(
+ new ExtendedIdBuilder().setId("identifier_value").build()).build()).build();
+ assertEquals(choiceContainerBA, entry.getValue());
+ }
+
+ @Test
+ public void orderedLisToNormalized() {
+ InstanceIdentifier<TopLevelList> ii = BA_TOP_LEVEL_LIST;
+ List<NestedList> nestedLists = new ArrayList<>();
+ nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("foo")).build());
+ nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("bar")).build());
+ TopLevelList topLevelList = new TopLevelListBuilder().setKey(TOP_LEVEL_LIST_FOO_KEY).setNestedList(nestedLists).build();
+ Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = registry.toNormalizedNode(ii, topLevelList);
+ MapEntryNode foo = mapEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+ TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .withChild(
+ ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME))
+ .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
+ .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar")).build()).build();
+ assertEquals(foo, entry.getValue());
+ }
+
+ @Test
+ public void orderedLisFromNormalized() {
+ MapEntryNode foo = mapEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+ TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+ .withChild(
+ ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME))
+ .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
+ .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar")).build()).build();
+ InstanceIdentifier<TopLevelList> ii = BA_TOP_LEVEL_LIST;
+
+ Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH, foo);
+ List<NestedList> nestedLists = new ArrayList<>();
+ nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("foo")).build());
+ nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("bar")).build());
+ TopLevelList topLevelList = new TopLevelListBuilder().setKey(TOP_LEVEL_LIST_FOO_KEY).setNestedList(nestedLists).build();
+ assertEquals(topLevelList, entry.getValue());
+ }
+}
return null;
}
final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
- final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf);
+ final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module);
genType.addComment(node.getDescription());
genType.setDescription(createDescription(node, genType.getFullyQualifiedName()));
genType.setModuleName(module.getName());
processUsesAugments(notification, module);
final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName,
- notification, BindingTypes.DATA_OBJECT);
+ notification, BindingTypes.DATA_OBJECT, module);
notificationInterface.addImplementsType(NOTIFICATION);
genCtx.get(module).addChildNodeType(notification, notificationInterface);
*/
private void groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module module) {
final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath());
- final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping);
+ final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping, module);
genCtx.get(module).addGroupingType(grouping.getPath(), genType);
resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.getChildNodes());
groupingsToGenTypes(module, grouping.getGroupings());
for (ChoiceCaseNode caseNode : caseNodes) {
if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
- final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
+ final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
caseTypeBuilder.addImplementsType(refChoiceType);
genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
for (DataSchemaNode caseNode : augmentedNodes) {
if (caseNode != null) {
final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
- final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
+ final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
caseTypeBuilder.addImplementsType(targetType);
SchemaNode parent = null;
return returnType.toInstance();
}
- private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {
- return addDefaultInterfaceDefinition(packageName, schemaNode, null);
+ private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
+ final Module module) {
+ return addDefaultInterfaceDefinition(packageName, schemaNode, null, module);
}
/**
* @return generated type builder <code>schemaNode</code>
*/
private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
- final Type parent) {
+ final Type parent, final Module module) {
final GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, "");
if (parent == null) {
it.addImplementsType(DATA_OBJECT);
}
if (schemaNode instanceof DataNodeContainer) {
+ groupingsToGenTypes(module, ((DataNodeContainer) schemaNode).getGroupings());
addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it);
}
package org.opendaylight.yangtools.sal.binding.generator.impl;
import com.google.common.collect.ImmutableList;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
-
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
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.Node;
import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
public InstanceIdentifier<? extends Object> deserialize(
final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier input) {
Class<?> baType = null;
- List<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument> biArgs = input.getPath();
- List<QName> scannedPath = new ArrayList<>(biArgs.size());
- List<InstanceIdentifier.PathArgument> baArgs = new ArrayList<InstanceIdentifier.PathArgument>(biArgs.size());
+ Iterable<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument> biArgs = input.getPathArguments();
+ List<QName> scannedPath = new ArrayList<>();
+ List<InstanceIdentifier.PathArgument> baArgs = new ArrayList<InstanceIdentifier.PathArgument>();
for (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument biArg : biArgs) {
scannedPath.add(biArg.getNodeType());
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
-
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-
import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
import org.opendaylight.yangtools.binding.generator.util.Types;
import org.opendaylight.yangtools.concepts.Delegator;
while (iterator.hasNext()) {
QName arg = iterator.next();
DataSchemaNode currentNode = previous.getDataChildByName(arg);
- if (currentNode == null && previous instanceof DataNodeContainer) {
+ if (currentNode == null) {
currentNode = searchInChoices(previous, arg);
}
if (currentNode instanceof DataNodeContainer) {
if (!parentQName.equals(choiceName)) {
// This item is instantiation of choice via uses in other YANG
// module
- if (choiceName.getNamespace().equals(schema.getQName())) {
+ if (choiceName.getNamespace().equals(schema.getQName().getNamespace())) {
// Original definition of grouping is in same namespace
// as original definition of case
// so for sure case is introduced via instantiation of
«generateFields(false)»
- «generateAugmentField(true)»
+ «generateAugmentField(false)»
«generateConstructorsFromIfcs(type)»
«generateFields(true)»
- «generateAugmentField(false)»
+ «generateAugmentField(true)»
«generateCopyConstructor(true)»
«ENDIF»
'''
- def private generateAugmentField(boolean init) '''
+ def private generateAugmentField(boolean isPrivate) '''
«IF augmentField != null»
- private «Map.importedName»<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> «augmentField.name» = new «HashMap.importedName»<>();
+ «IF isPrivate»private «ENDIF»«Map.importedName»<«Class.importedName»<? extends «augmentField.returnType.importedName»>, «augmentField.returnType.importedName»> «augmentField.name» = new «HashMap.importedName»<>();
«ENDIF»
'''
--- /dev/null
+/*
+ * Copyright (c) 2013 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.yangtools.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_TEST;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test correct code generation.
+ *
+ */
+public class NestedGroupingCompilationTest extends BaseCompilationTest {
+
+ @Test
+ public void testListGeneration() throws Exception {
+ final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "nested-grouping");
+ assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+ final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "nested-grouping");
+ assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+ generateTestSources("/compilation/nested-grouping", sourcesOutputDir);
+
+ // Test if all sources are generated
+ File parent = new File(sourcesOutputDir, NS_TEST);
+ File foo = new File(parent, "Foo.java");
+ File fooBuilder = new File(parent, "FooBuilder.java");
+ File testData = new File(parent, "TestData.java");
+ File fooDir = new File(parent, "foo");
+ assertTrue(foo.exists());
+ assertTrue(fooBuilder.exists());
+ assertTrue(testData.exists());
+ assertTrue(fooDir.exists());
+ assertFilesCount(parent, 4);
+
+ parent = new File(parent, "foo");
+ File bar = new File(parent, "Bar.java");
+ assertTrue(bar.exists());
+ assertFilesCount(parent, 1);
+
+ // Test if sources are compilable
+ testCompilation(sourcesOutputDir, compiledOutputDir);
+
+ ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+ Class<?> fooClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Foo", true, loader);
+ Class<?> barClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.foo.Bar", true, loader);
+
+ // Test generated 'foo'
+ assertTrue(fooClass.isInterface());
+ assertImplementsIfc(fooClass, barClass);
+
+ cleanUp(sourcesOutputDir, compiledOutputDir);
+ }
+
+ private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+ final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+ final SchemaContext context = parser.parseFiles(sourceFiles);
+ final List<Type> types = bindingGenerator.generateTypes(context);
+ final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+ generator.generateToFile(sourcesOutputDir);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 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
+ */
+module test {
+ yang-version 1;
+ namespace "urn:opendaylight:test";
+ prefix "t";
+
+ revision "2013-10-08" {
+ }
+
+ container foo {
+ grouping bar {
+ leaf id {
+ type int32;
+ }
+ }
+ uses bar;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2013 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-generator</artifactId>
+ <version>0.6.2-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ </dependencies>
+
+ <artifactId>binding-test-model</artifactId>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ target/generated-sources/sal
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.sal.test.model.util;
+
+import com.google.common.collect.ImmutableList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListKey;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Arrays;
+
+public class ListsBindingUtils {
+
+ private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+
+ private ListsBindingUtils() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+ public static final TopLevelListKey TOP_BAR_KEY = new TopLevelListKey("bar");
+ public static final ListViaUsesKey USES_ONE_KEY = new ListViaUsesKey("one");
+ public static final ListViaUsesKey USES_TWO_KEY = new ListViaUsesKey("two");
+
+
+ public static InstanceIdentifier<TopLevelList> path(final TopLevelListKey key) {
+ return TOP_PATH.child(TopLevelList.class, key);
+ }
+
+ public static InstanceIdentifier<NestedList> path(final TopLevelListKey top,final NestedListKey nested) {
+ return path(top).child(NestedList.class, nested);
+ }
+
+ public static InstanceIdentifier<ListViaUses> path(final TopLevelListKey top,final ListViaUsesKey uses) {
+ return path(top).augmentation(TreeComplexUsesAugment.class).child(ListViaUses.class, uses);
+ }
+
+ public static <T extends DataObject & Augmentation<TopLevelList>> InstanceIdentifier<T> path(final TopLevelListKey key, final Class<T> augmentation) {
+ return path(key).augmentation(augmentation);
+ }
+
+ public static Top top(final TopLevelList... listItems) {
+ return new TopBuilder().setTopLevelList(Arrays.asList(listItems)).build();
+ }
+
+ public static TopLevelList topLevelList(final TopLevelListKey key) {
+ return new TopLevelListBuilder().setKey(key).build();
+ }
+
+ public static TopLevelList topLevelList(final TopLevelListKey key, final TreeComplexUsesAugment augment) {
+ TopLevelListBuilder builder = new TopLevelListBuilder().setKey(key);
+ builder.addAugmentation(TreeComplexUsesAugment.class, augment);
+ return builder.build();
+ }
+
+ public static TreeComplexUsesAugment complexUsesAugment(final ListViaUsesKey... keys) {
+ ImmutableList.Builder<ListViaUses> listViaUses = ImmutableList.<ListViaUses> builder();
+ for (ListViaUsesKey key : keys) {
+ listViaUses.add(new ListViaUsesBuilder().setKey(key).build());
+ }
+ return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
+ }
+
+ public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+ return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+ }
+
+}
--- /dev/null
+module opendaylight-yangtools-augment-test {
+
+ namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:augment";
+ prefix aug-test;
+
+ import opendaylight-yangtools-binding-test {
+ prefix test;
+ }
+ import yang-ext {
+ prefix ext;
+ }
+
+ description
+ "This module contains a collection of YANG augmentations used for
+ some test cases.";
+
+ revision 2014-07-09 {
+ description
+ "Test model for testing data broker with nested lists.";
+ }
+
+ grouping leaf-from-grouping {
+ leaf leaf-from-grouping {
+ type string;
+ }
+ }
+
+ grouping complex-from-grouping {
+ container container-with-uses {
+ uses leaf-from-grouping;
+ }
+ list list-via-uses {
+ key "name";
+ leaf name {
+ type string;
+ }
+ }
+
+ }
+
+ augment "/test:top/test:top-level-list" {
+ ext:augment-identifier tree-leaf-only-uses-augment;
+ uses leaf-from-grouping;
+ }
+
+ augment "/test:put-top/test:input/test:top-level-list" {
+ ext:augment-identifier rpc-leaf-only-uses-augment;
+ uses leaf-from-grouping;
+ }
+
+ augment "/test:top/test:top-level-list" {
+ ext:augment-identifier tree-complex-uses-augment;
+ uses complex-from-grouping;
+ }
+
+ augment "/test:put-top/test:input/test:top-level-list" {
+ ext:augment-identifier rpc-complex-uses-augment;
+ uses complex-from-grouping;
+ }
+
+ augment "/test:top/test:top-level-list" {
+ ext:augment-identifier tree-leaf-only-augment;
+
+ leaf simple-value {
+ type string;
+ }
+ }
+
+ augment "/test:top/test:top-level-list" {
+ ext:augment-identifier tree-second-leaf-only-augment;
+
+ leaf second-simple-value {
+ type string;
+ }
+ }
+
+ augment "/test:put-top/test:input/test:top-level-list" {
+ ext:augment-identifier rpc-leaf-only-augment;
+
+ leaf simple-value {
+ type string;
+ }
+ }
+
+ augment "/test:put-top/test:input/test:top-level-list" {
+ ext:augment-identifier rpc-second-leaf-only-augment;
+
+ leaf second-simple-value {
+ type string;
+ }
+ }
+
+ augment "/test:top/test:top-level-list/test:choice-in-list" {
+ case simple-via-uses {
+ uses leaf-from-grouping;
+ }
+ case complex-via-uses {
+ uses complex-from-grouping;
+ }
+ }
+
+ augment "/test:put-top/test:input/test:top-level-list/test:choice-in-list" {
+ case simple-via-uses {
+ uses leaf-from-grouping;
+ }
+ case complex-via-uses-with-different-name {
+ uses complex-from-grouping;
+ }
+ }
+
+}
--- /dev/null
+module opendaylight-yangtools-binding-test {
+
+ namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:binding";
+ prefix list-test;
+
+
+ description
+ "This module contains a collection of YANG definitions used for
+ some test cases.";
+
+ revision 2014-07-01 {
+ description
+ "Test model for testing data broker with nested lists.";
+ }
+
+ grouping two-level-list {
+ list top-level-list {
+ description
+ "Top Level List";
+ key "name";
+ leaf name {
+ type string;
+ }
+
+ choice choice-in-list {
+ case simple-case {
+ leaf simple {
+ type string;
+ }
+ }
+ }
+
+ list nested-list {
+ key "name";
+ leaf name {
+ type string;
+ }
+ leaf type {
+ type string;
+ mandatory true;
+ description
+ "Mandatory type of list.";
+ }
+ ordered-by user;
+ description
+ "A list of service functions that compose the service chain";
+ }
+ }
+ leaf-list top-level-leaf-list {
+ type string;
+ }
+ }
+
+ grouping choice {
+ choice identifier {
+ case simple {
+ container simple-id {
+ leaf id {
+ type int32;
+ }
+ }
+ }
+ case extended {
+ container extended-id {
+ leaf id {
+ type string;
+ }
+ }
+ }
+ }
+ }
+
+ container top {
+ uses two-level-list;
+ }
+
+ container choice-container {
+ uses choice;
+ }
+
+ rpc put-top {
+ input {
+ uses two-level-list;
+ }
+ }
+}
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.BaseEncoding;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.apache.commons.lang3.StringEscapeUtils;
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
import org.opendaylight.yangtools.yang.model.util.Uint8;
import org.opendaylight.yangtools.yang.model.util.UnionType;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import com.google.common.io.BaseEncoding;
-
public final class TypeProviderImpl implements TypeProvider {
private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
final List<GeneratedTOBuilder> genTOBuilders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
typedef, typeDefName, parentNode);
GeneratedTOBuilder resultTOBuilder = null;
- if (!genTOBuilders.isEmpty()) {
- resultTOBuilder = genTOBuilders.remove(0);
- for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
- resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
- }
+ if (genTOBuilders.isEmpty()) {
+ throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typedef);
+ }
+
+ resultTOBuilder = genTOBuilders.remove(0);
+ for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
+ resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
}
final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value");
final String packageName = packageNameForGeneratedType(basePackageName, typedef.getPath());
final String typeDefTOName = typedef.getQName().getLocalName();
- if ((packageName != null) && (typedef != null) && (typeDefTOName != null)) {
+ if ((packageName != null) && (typeDefTOName != null)) {
final String genTOName = BindingMapping.getClassName(typeDefTOName);
final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTOName);
typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
}
// keys are in ascending order
- Set<Integer> depths = typeDefinitionsDepths.keySet();
- for (Integer depth : depths) {
- sortedTypeDefinition.addAll(typeDefinitionsDepths.get(depth));
+ for (Map.Entry<Integer, List<TypeDefinition<?>>> entry : typeDefinitionsDepths.entrySet()) {
+ sortedTypeDefinition.addAll(entry.getValue());
}
return sortedTypeDefinition;
</ul>
«ENDIF»
- «IF !path.path.empty»
+ «IF path.pathArguments.iterator.hasNext»
<h3>XML example</h3>
- «nodes.xmlExample(path.path.last.nodeType,path)»
+ «nodes.xmlExample(path.pathArguments.last.nodeType,path)»
</h3>
«ENDIF»
«FOR childNode : containers»
def header(int level,YangInstanceIdentifier name) '''
- <h«level» id="«FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">
- «FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»
+ <h«level» id="«FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">
+ «FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»
</h«level»>
'''
}
def CharSequence localLink(YangInstanceIdentifier identifier, CharSequence text) '''
- <a href="#«FOR cmp : identifier.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
+ <a href="#«FOR cmp : identifier.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
'''
append(currentModule.name)
append(":")
var previous = false;
- for(arg : identifier.path) {
+ for(arg : identifier.pathArguments) {
if(previous) append("/")
append(arg.nodeType.localName);
previous = true;
testCompilation(sourcesOutputDir, compiledOutputDir);
// Create URLClassLoader
- File[] roots = File.listRoots();
- URL[] urls = new URL[roots.length + 1];
- for (int i = 0; i < roots.length; i++) {
- urls[i] = roots[i].toURI().toURL();
-
- }
- urls[roots.length] = compiledOutputDir.toURI().toURL();
+ URL[] urls = new URL[2];
+ urls[0] = compiledOutputDir.toURI().toURL();
+ urls[1] = new File(System.getProperty("user.dir")).toURI().toURL();
ClassLoader loader = new URLClassLoader(urls);
// Load class
private static List<File> getSourceFiles(String path) throws Exception {
final URI resPath = YangModuleInfoCompilationTest.class.getResource(path).toURI();
final File sourcesDir = new File(resPath);
+ final URI currentDir = new File(System.getProperty("user.dir")).toURI();
if (sourcesDir.exists()) {
final List<File> sourceFiles = new ArrayList<>();
final File[] fileArray = sourcesDir.listFiles();
if (fileArray == null) {
throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
}
- sourceFiles.addAll(Arrays.asList(fileArray));
+ for (File sourceFile : fileArray) {
+ sourceFiles.add(new File(currentDir.relativize(sourceFile.toURI()).toString()));
+ }
return sourceFiles;
} else {
throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
<module>binding-java-api-generator</module>
<module>binding-type-provider</module>
<module>maven-sal-api-gen-plugin</module>
+ <module>binding-test-model</module>
<module>binding-data-codec</module>
</modules>
</dependency>
<!-- Local Dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-test-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>binding-model-api</artifactId>
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.collect.Sets;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public static Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Augmentable<?> input) {
return AugmentationFieldGetter.getGetter(input.getClass()).getAugmentations(input);
}
+
+ /**
+ *
+ * Determines if two augmentation classes or case classes represents same data.
+ * <p>
+ * Two augmentations or cases could be substituted only if and if:
+ * <ul>
+ * <li>Both implements same interfaces</li>
+ * <li>Both have same children</li>
+ * <li>If augmentations: Both have same augmentation target class. Target class was generated for data node in grouping.</li>
+ * <li>If cases: Both are from same choice. Choice class was generated for data node in grouping.</li>
+ * </ul>
+ * <p>
+ * <b>Explanation:</b> Binding Specification reuses classes generated for groupings as part of normal data tree,
+ * this classes from grouping could be used at various locations and user may not be aware of it
+ * and may use incorrect case or augmentation in particular subtree (via copy constructors, etc).
+ *
+ * @param potential Class which is potential substition
+ * @param target Class which should be used at particular subtree
+ * @return true if and only if classes represents same data.
+ */
+ @SuppressWarnings({"rawtypes","unchecked"})
+ public static boolean isSubstitutionFor(Class potential, Class target) {
+ HashSet<Class> subImplemented = Sets.newHashSet(potential.getInterfaces());
+ HashSet<Class> targetImplemented = Sets.newHashSet(target.getInterfaces());
+ if(!subImplemented.equals(targetImplemented)) {
+ return false;
+ }
+ if(Augmentation.class.isAssignableFrom(potential)
+ && !BindingReflections.findAugmentationTarget(potential).equals(BindingReflections.findAugmentationTarget(target))) {
+ return false;
+ }
+ for(Method potentialMethod : potential.getMethods()) {
+ try {
+ Method targetMethod = target.getMethod(potentialMethod.getName(), potentialMethod.getParameterTypes());
+ if(!potentialMethod.getReturnType().equals(targetMethod.getReturnType())) {
+ return false;
+ }
+ } catch (NoSuchMethodException e) {
+ // Counterpart method is missing, so classes could not be substituted.
+ return false;
+ } catch (SecurityException e) {
+ throw new IllegalStateException("Could not compare methods",e);
+ }
+ }
+ return true;
+ }
}