summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--infra/test-utils/test-api/src/main/yang/hc-data.yang21
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/AbstractYangContextHolder.java42
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessor.java89
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/HoneycombTestRunner.java47
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ListNodeDataProcessor.java84
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangContextProducer.java16
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessor.java129
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessorRegistry.java68
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/annotations/InjectablesProcessor.java33
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/ChildNodeDataFactory.java77
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/RootNodeDataFactory.java42
-rw-r--r--infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/YangDataFactory.java109
-rw-r--r--infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/AbstractYangDataProcessorTest.java48
-rw-r--r--infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessorTest.java60
-rw-r--r--infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/HoneycombTestRunnerContainerTest.java (renamed from infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/HoneycombTestRunnerTest.java)33
-rw-r--r--infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/InjectionTestData.java46
-rw-r--r--infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ListNodeDataProcessorTest.java79
-rw-r--r--infra/test-utils/test-tools/src/test/resources/augmentListEntry.json10
-rw-r--r--infra/test-utils/test-tools/src/test/resources/nestedListEntry.json10
-rw-r--r--infra/test-utils/test-tools/src/test/resources/rootListEntry.json10
-rw-r--r--infra/test-utils/test-tools/src/test/resources/simpleListEntry.json10
-rw-r--r--infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/JsonUtils.java47
22 files changed, 806 insertions, 304 deletions
diff --git a/infra/test-utils/test-api/src/main/yang/hc-data.yang b/infra/test-utils/test-api/src/main/yang/hc-data.yang
index a817a249f..6cd524565 100644
--- a/infra/test-utils/test-api/src/main/yang/hc-data.yang
+++ b/infra/test-utils/test-api/src/main/yang/hc-data.yang
@@ -12,6 +12,13 @@ module hc-data{
prefix "ext";
}
+ list root-list {
+ key root-name;
+ leaf root-name{
+ type string;
+ }
+ }
+
container simple-container{
list simple-list{
key name;
@@ -23,6 +30,13 @@ module hc-data{
type string;
}
}
+
+ list nested-list {
+ key nested-name;
+ leaf nested-name {
+ type string;
+ }
+ }
}
container nested-container{
@@ -67,5 +81,12 @@ module hc-data{
leaf name-in-augment{
type string;
}
+
+ list list-in-augment{
+ key key-in-augment;
+ leaf key-in-augment{
+ type string;
+ }
+ }
}
} \ No newline at end of file
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/AbstractYangContextHolder.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/AbstractYangContextHolder.java
new file mode 100644
index 000000000..93360d25a
--- /dev/null
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/AbstractYangContextHolder.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import javax.annotation.Nonnull;
+
+abstract class AbstractYangContextHolder {
+
+ private final SchemaContext schemaContext;
+ private final BindingToNormalizedNodeCodec serializer;
+
+ AbstractYangContextHolder(@Nonnull final SchemaContext schemaContext,
+ @Nonnull final BindingToNormalizedNodeCodec serializer){
+ this.schemaContext=schemaContext;
+ this.serializer=serializer;
+ }
+
+ SchemaContext schemaContext() {
+ return schemaContext;
+ }
+
+ BindingToNormalizedNodeCodec serializer() {
+ return serializer;
+ }
+}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessor.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessor.java
new file mode 100644
index 000000000..089bb43cd
--- /dev/null
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessor.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+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.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.io.InputStream;
+
+import static com.google.common.base.Preconditions.checkState;
+import static io.fd.honeycomb.translate.util.JsonUtils.readContainerEntryJson;
+import static io.fd.honeycomb.translate.util.JsonUtils.readJson;
+
+final class ContainerNodeDataProcessor extends AbstractYangContextHolder implements YangDataProcessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ContainerNodeDataProcessor.class);
+
+ ContainerNodeDataProcessor(@Nonnull SchemaContext schemaContext, @Nonnull BindingToNormalizedNodeCodec serializer) {
+ super(schemaContext, serializer);
+ }
+
+ @Nonnull
+ @Override
+ public DataObject getNodeData(@Nonnull YangInstanceIdentifier yangInstanceIdentifier, @Nonnull String resourcePath) {
+
+ final InputStream resourceStream = this.getClass().getResourceAsStream(resourcePath);
+ final YangInstanceIdentifier nodeParent = getNodeParent(yangInstanceIdentifier).orElse(null);
+ final SchemaNode parentSchema = parentSchema(schemaContext(), serializer(), nodeParent, () -> LOG);
+
+ // to be able to process containers in root of model
+ if (isRoot(yangInstanceIdentifier)) {
+ // if root ,read as root
+ final ContainerNode data = readJson(schemaContext(), resourceStream, parentSchema);
+ checkState(data.getValue().size() == 1, "Single root expected in %s", resourcePath);
+ //then extracts first child
+ final QName rootNodeType = data.getValue().iterator().next().getNodeType();
+ final YangInstanceIdentifier realIdentifier = YangInstanceIdentifier.of(rootNodeType);
+ return nodeBinding(serializer(), realIdentifier, data).getValue();
+ } else {
+ // reads just container
+ final YangInstanceIdentifier.NodeIdentifier nodeIdentifier = containerNodeIdentifier(yangInstanceIdentifier);
+ final ContainerNode data = readContainerEntryJson(schemaContext(), resourceStream, parentSchema, nodeIdentifier);
+ return nodeBinding(serializer(), yangInstanceIdentifier, data.getValue().iterator().next()).getValue();
+ }
+ }
+
+ @Override
+ public boolean canProcess(@Nonnull YangInstanceIdentifier identifier) {
+ return isRoot(identifier) ||
+ isContainer(identifierBinding(serializer(), identifier).getTargetType());
+ }
+
+ private static boolean isContainer(final Class targetType) {
+ return !Identifiable.class.isAssignableFrom(targetType)
+ && !Augmentation.class.isAssignableFrom(targetType);
+ }
+
+ private static YangInstanceIdentifier.NodeIdentifier containerNodeIdentifier(@Nonnull final YangInstanceIdentifier nodeIdentifier) {
+ return java.util.Optional.ofNullable(nodeIdentifier.getLastPathArgument())
+ .filter(pathArgument -> pathArgument instanceof YangInstanceIdentifier.NodeIdentifier)
+ .map(YangInstanceIdentifier.NodeIdentifier.class::cast)
+ .orElseThrow(() -> new IllegalArgumentException(
+ String.format("Unable to create container node identifier from %s", nodeIdentifier)));
+ }
+}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/HoneycombTestRunner.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/HoneycombTestRunner.java
index 906a5fc87..0f8b1b9af 100644
--- a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/HoneycombTestRunner.java
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/HoneycombTestRunner.java
@@ -17,29 +17,23 @@
package io.fd.honeycomb.test.tools;
import io.fd.honeycomb.test.tools.annotations.InjectablesProcessor;
-import io.fd.honeycomb.test.tools.factories.ChildNodeDataFactory;
-import io.fd.honeycomb.test.tools.factories.RootNodeDataFactory;
-import java.io.IOException;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Parameter;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import javax.annotation.Nullable;
-import org.apache.commons.lang3.StringUtils;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Parameter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
public class HoneycombTestRunner extends BlockJUnit4ClassRunner implements YangContextProducer, InjectablesProcessor {
private static final Logger LOG = LoggerFactory.getLogger(HoneycombTestRunner.class);
@@ -48,8 +42,7 @@ public class HoneycombTestRunner extends BlockJUnit4ClassRunner implements YangC
private BindingToNormalizedNodeCodec serializer;
private AbstractModuleStringInstanceIdentifierCodec iidParser;
- private ChildNodeDataFactory childNodeDataFactory;
- private RootNodeDataFactory rootNodeDataFactory;
+ private YangDataProcessorRegistry processorRegistry;
public HoneycombTestRunner(final Class<?> klass) throws InitializationError {
super(klass);
@@ -64,12 +57,11 @@ public class HoneycombTestRunner extends BlockJUnit4ClassRunner implements YangC
final ModuleInfoBackedContext ctx = getCheckedModuleInfoContext(test);
schemaContext = ctx.getSchemaContext();
// Create serializer from it in order to later transform NormalizedNodes into BA
- serializer = createSerializer(ctx, schemaContext);
+ serializer = createSerializer(ctx);
// Create InstanceIdentifier Codec in order to later transform string represented IID into YangInstanceIdentifier
iidParser = getIIDCodec(ctx);
- childNodeDataFactory = new ChildNodeDataFactory(schemaContext, serializer, iidParser);
- rootNodeDataFactory = new RootNodeDataFactory(schemaContext, serializer, iidParser);
+ processorRegistry = YangDataProcessorRegistry.create(schemaContext, serializer);
injectFields(test);
return test;
@@ -83,7 +75,7 @@ public class HoneycombTestRunner extends BlockJUnit4ClassRunner implements YangC
/**
* Allows method parameters injection
- * */
+ */
@Override
protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
return new InjectableTestMethodInvoker(method, test, Arrays.stream(method.getMethod().getParameters())
@@ -94,7 +86,7 @@ public class HoneycombTestRunner extends BlockJUnit4ClassRunner implements YangC
private Object injectValueOrNull(final Parameter parameter) {
return isInjectable(parameter)
- ? getData(resourcePath(parameter), instanceIdentifier(parameter).orNull(), parameter.getType())
+ ? processorRegistry.getNodeData(instanceIdentifier(iidParser, parameter), resourcePath(parameter))
: null;
}
@@ -107,22 +99,7 @@ public class HoneycombTestRunner extends BlockJUnit4ClassRunner implements YangC
injectableFields(testInstance.getClass()).forEach(field -> {
LOG.debug("Processing field {}", field);
injectField(field, testInstance,
- getData(resourcePath(field), instanceIdentifier(field).orNull(), field.getType()));
+ processorRegistry.getNodeData(instanceIdentifier(iidParser, field), resourcePath(field)));
});
}
-
- private DataObject getData(final String resourcePath, @Nullable final String identifier,
- final Class<?> injectedType) {
- try {
- if (StringUtils.isNotEmpty(identifier)) {
- LOG.debug("Processing {} as child node {}", injectedType, identifier);
- return childNodeDataFactory.getChildNodeData(identifier, resourcePath);
- } else {
- LOG.debug("Processing {} as root node", injectedType);
- return rootNodeDataFactory.getRootNodeData(getRootInstanceIdentifier(injectedType), resourcePath);
- }
- } catch (DeserializationException | IOException e) {
- throw new IllegalStateException(e);
- }
- }
}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ListNodeDataProcessor.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ListNodeDataProcessor.java
new file mode 100644
index 000000000..375f55307
--- /dev/null
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/ListNodeDataProcessor.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.io.InputStream;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static io.fd.honeycomb.translate.util.JsonUtils.readListEntryFromJson;
+
+/**
+ * json --> BA processor for list entry data
+ */
+final class ListNodeDataProcessor extends AbstractYangContextHolder implements YangDataProcessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ListNodeDataProcessor.class);
+
+ ListNodeDataProcessor(@Nonnull final SchemaContext schemaContext,
+ @Nonnull final BindingToNormalizedNodeCodec serializer) {
+ super(schemaContext, serializer);
+ }
+
+ @Nonnull
+ @Override
+ public DataObject getNodeData(@Nonnull final YangInstanceIdentifier nodeIdentifier,
+ @Nonnull final String resourcePath) {
+ checkArgument(canProcess(nodeIdentifier), "Cannot process identifier %s", nodeIdentifier);
+ final YangInstanceIdentifier listParent = listNodeParent(nodeIdentifier);
+ final YangInstanceIdentifier.NodeIdentifierWithPredicates keyedNodeIdentifier = listNodeIdentifier(nodeIdentifier);
+ final InputStream resourceStream = this.getClass().getResourceAsStream(resourcePath);
+ final SchemaNode parentSchemaNode = parentSchema(schemaContext(), serializer(), listParent, () -> LOG);
+ final MapEntryNode data = readListEntryFromJson(schemaContext(), resourceStream, parentSchemaNode, keyedNodeIdentifier);
+
+ return nodeBinding(serializer(), nodeIdentifier, data).getValue();
+ }
+
+ @Override
+ public boolean canProcess(@Nonnull final YangInstanceIdentifier identifier) {
+ return !isRoot(identifier) &&
+ Identifiable.class.isAssignableFrom(identifierBinding(serializer(), identifier).getTargetType());
+ }
+
+ private YangInstanceIdentifier listNodeParent(@Nonnull final YangInstanceIdentifier nodeIdentifier) {
+ // if it is list, real parent is second to last
+ return getNodeParent(nodeIdentifier).map(parent -> getNodeParent(parent).orElse(null))
+ .orElseThrow(() -> new IllegalArgumentException(
+ String.format("Unable to get parent for list node from %s", nodeIdentifier)));
+ }
+
+ private static YangInstanceIdentifier.NodeIdentifierWithPredicates listNodeIdentifier(@Nonnull final YangInstanceIdentifier nodeIdentifier) {
+ return java.util.Optional.ofNullable(nodeIdentifier.getLastPathArgument())
+ .filter(pathArgument -> pathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates)
+ .map(YangInstanceIdentifier.NodeIdentifierWithPredicates.class::cast)
+ .orElseThrow(() -> new IllegalArgumentException(
+ String.format("Unable to create list node identifier from %s", nodeIdentifier)));
+ }
+}
+
+
+
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangContextProducer.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangContextProducer.java
index 23af9733d..017a68c9f 100644
--- a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangContextProducer.java
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangContextProducer.java
@@ -16,12 +16,7 @@
package io.fd.honeycomb.test.tools;
-import static com.google.common.base.Preconditions.checkState;
-
import io.fd.honeycomb.test.tools.annotations.SchemaContextProvider;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import javassist.ClassPool;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
@@ -34,6 +29,12 @@ import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactory;
import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static com.google.common.base.Preconditions.checkState;
+
/**
* Common logic to initialize serializers/deserializers/etc while working with yang based data
*/
@@ -67,14 +68,13 @@ interface YangContextProducer {
return (AbstractModuleStringInstanceIdentifierCodec) cstr.newInstance(ctx.getSchemaContext(), jsonCodecFactory);
}
- default BindingToNormalizedNodeCodec createSerializer(final ModuleInfoBackedContext moduleInfoBackedContext,
- final SchemaContext schemaContexts) {
+ default BindingToNormalizedNodeCodec createSerializer(final ModuleInfoBackedContext moduleInfoBackedContext) {
final BindingNormalizedNodeCodecRegistry codecRegistry =
new BindingNormalizedNodeCodecRegistry(
StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())));
codecRegistry
- .onBindingRuntimeContextUpdated(BindingRuntimeContext.create(moduleInfoBackedContext, schemaContexts));
+ .onBindingRuntimeContextUpdated(BindingRuntimeContext.create(moduleInfoBackedContext, moduleInfoBackedContext.getSchemaContext()));
return new BindingToNormalizedNodeCodec(moduleInfoBackedContext, codecRegistry);
}
}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessor.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessor.java
new file mode 100644
index 000000000..a353e4b3b
--- /dev/null
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessor.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingSchemaContextUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.slf4j.Logger;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.AbstractMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Supplier;
+
+interface YangDataProcessor {
+
+ /**
+ * Attempts to find data in file specified by <b>resourcePath</b>,<br>
+ * and translate it to BA object
+ *
+ * @param yangInstanceIdentifier identifier of path to read
+ * @param resourcePath path of resource file to load
+ */
+ @Nonnull
+ DataObject getNodeData(@Nonnull final YangInstanceIdentifier yangInstanceIdentifier,
+ @Nonnull final String resourcePath);
+
+ /**
+ * Verifies if provided identifier is identifying node processed by this processor
+ *
+ * @param identifier node identifier
+ */
+ boolean canProcess(@Nonnull final YangInstanceIdentifier identifier);
+
+ default boolean isRoot(@Nonnull final YangInstanceIdentifier identifier) {
+ return identifier.getPathArguments().isEmpty();
+ }
+
+ @Nonnull
+ default Optional<YangInstanceIdentifier> getNodeParent(@Nonnull final YangInstanceIdentifier identifier) {
+ return Optional.ofNullable(identifier.getParent());
+ }
+
+ @Nonnull
+ default SchemaNode parentSchema(@Nonnull final SchemaContext schemaContext,
+ @Nonnull final BindingToNormalizedNodeCodec serializer,
+ @Nullable final YangInstanceIdentifier parentYangId,
+ @Nonnull final Supplier<Logger> logProvider) {
+ // null or root
+ if (parentYangId == null || parentYangId.getPathArguments().size() == 0) {
+ // no parent == use schema context as root context
+ logProvider.get().info("Parent is null, providing schema context as parent node");
+ return schemaContext;
+ }
+
+ final com.google.common.base.Optional<InstanceIdentifier<? extends DataObject>> parentInstanceId;
+ try {
+ parentInstanceId = serializer.toBinding(parentYangId);
+ } catch (DeserializationException e) {
+ throw new IllegalArgumentException(String.format("Unable to deserialize %s", parentYangId));
+ }
+
+ if (!parentInstanceId.isPresent()) {
+ throw new IllegalStateException(String.format("Unable to resolve %s to instance identifier", parentYangId));
+ }
+
+ final com.google.common.base.Optional<DataNodeContainer> dataNodeContainerOptional =
+ BindingSchemaContextUtils.findDataNodeContainer(schemaContext, parentInstanceId.get());
+
+
+ if (!dataNodeContainerOptional.isPresent()) {
+ throw new IllegalArgumentException(String.format("Error finding DataNodeContainer for %s", parentInstanceId.get()));
+ }
+
+ final DataNodeContainer parentNode = dataNodeContainerOptional.get();
+ logProvider.get().info("Parent schema node resolved as {}", parentNode);
+ return (SchemaNode) parentNode;
+ }
+
+ @Nonnull
+ default Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> nodeBinding(@Nonnull final BindingToNormalizedNodeCodec serializer,
+ @Nonnull final YangInstanceIdentifier identifier,
+ @Nonnull final NormalizedNode<?, ?> data) {
+ try {
+ return serializer.toBinding(new AbstractMap.SimpleImmutableEntry<>(identifier, data))
+ .or(() -> {
+ throw new IllegalArgumentException(String.format("Unable to create node binding for %s|%s", identifier, data));
+ });
+ } catch (DeserializationException e) {
+ throw new IllegalArgumentException(String.format("Unable to deserialize node %s|%s", identifier, data));
+ }
+ }
+
+ @Nonnull
+ default InstanceIdentifier<? extends DataObject> identifierBinding(@Nonnull final BindingToNormalizedNodeCodec serializer,
+ @Nonnull final YangInstanceIdentifier identifier) {
+ try {
+ return serializer.toBinding(identifier)
+ .or(() -> {
+ throw new IllegalArgumentException(String.format("Unable convert %s to binding", identifier));
+ });
+ } catch (DeserializationException e) {
+ throw new IllegalArgumentException(String.format("Unable to deserialize %s", identifier));
+ }
+ }
+}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessorRegistry.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessorRegistry.java
new file mode 100644
index 000000000..d23cd59c1
--- /dev/null
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/YangDataProcessorRegistry.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import javax.annotation.Nonnull;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Process yang data from json to BA Objects
+ */
+final class YangDataProcessorRegistry {
+
+ private final List<YangDataProcessor> processors;
+
+ private YangDataProcessorRegistry(@Nonnull final SchemaContext context,
+ @Nonnull final BindingToNormalizedNodeCodec codec) {
+ // linked should be faster for iteration
+ processors = new LinkedList<>();
+ processors.add(new ListNodeDataProcessor(context, codec));
+ processors.add(new ContainerNodeDataProcessor(context, codec));
+ }
+
+ static YangDataProcessorRegistry create(@Nonnull final SchemaContext context,
+ @Nonnull final BindingToNormalizedNodeCodec codec) {
+ return new YangDataProcessorRegistry(context, codec);
+ }
+
+ @Nonnull
+ DataObject getNodeData(@Nonnull final YangInstanceIdentifier yangInstanceIdentifier,
+ @Nonnull final String resourcePath) {
+ return pickProcessor(yangInstanceIdentifier).getNodeData(yangInstanceIdentifier, resourcePath);
+ }
+
+ private YangDataProcessor pickProcessor(final YangInstanceIdentifier yangInstanceIdentifier) {
+ final List<YangDataProcessor> eligibleProcessors = processors.stream()
+ .filter(processors -> processors.canProcess(yangInstanceIdentifier))
+ .collect(Collectors.toList());
+
+ // canProcess should be exclusive for node type, but just in case
+ checkState(eligibleProcessors.size() == 1,
+ "No single eligible processor found, matches=[%s]", eligibleProcessors);
+
+ return eligibleProcessors.get(0);
+ }
+}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/annotations/InjectablesProcessor.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/annotations/InjectablesProcessor.java
index c364938ed..216d8353b 100644
--- a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/annotations/InjectablesProcessor.java
+++ b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/annotations/InjectablesProcessor.java
@@ -16,22 +16,21 @@
package io.fd.honeycomb.test.tools.annotations;
-import static io.fd.honeycomb.test.tools.annotations.InjectTestData.NO_ID;
-
-import com.google.common.base.Optional;
-import java.lang.reflect.Field;
-import java.lang.reflect.Parameter;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
import org.apache.commons.lang3.reflect.FieldUtils;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.$YangModuleInfoImpl;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
+
+import javax.annotation.Nonnull;
+import java.lang.reflect.Field;
+import java.lang.reflect.Parameter;
+import java.util.List;
+import java.util.Set;
+
+import static io.fd.honeycomb.test.tools.annotations.InjectTestData.NO_ID;
/**
* Common logic for @InjectTestData
@@ -54,23 +53,23 @@ public interface InjectablesProcessor {
return parameter.getAnnotation(InjectTestData.class).resourcePath();
}
- default Optional<String> instanceIdentifier(final Field field) {
+ default YangInstanceIdentifier instanceIdentifier(@Nonnull final AbstractModuleStringInstanceIdentifierCodec parser, @Nonnull final Field field) {
final String identifier = field.getAnnotation(InjectTestData.class).id();
// == used instead of equals to ensure constant was used
if (NO_ID.equals(identifier)) {
- return Optional.absent();
+ return getRootInstanceIdentifier(field.getType());
} else {
- return Optional.of(identifier);
+ return parser.deserialize(identifier);
}
}
- default Optional<String> instanceIdentifier(final Parameter parameter) {
+ default YangInstanceIdentifier instanceIdentifier(@Nonnull final AbstractModuleStringInstanceIdentifierCodec parser, @Nonnull final Parameter parameter) {
final String identifier = parameter.getAnnotation(InjectTestData.class).id();
// == used instead of equals to ensure constant was used
if (NO_ID.equals(identifier)) {
- return Optional.absent();
+ return getRootInstanceIdentifier(parameter.getType());
} else {
- return Optional.of(identifier);
+ return parser.deserialize(identifier);
}
}
@@ -83,7 +82,7 @@ public interface InjectablesProcessor {
}
}
- default YangInstanceIdentifier getRootInstanceIdentifier(final Class type) {
+ static YangInstanceIdentifier getRootInstanceIdentifier(final Class type) {
try {
return YangInstanceIdentifier.of(QName.class.cast(type.getField("QNAME").get(null)));
} catch (IllegalAccessException e) {
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/ChildNodeDataFactory.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/ChildNodeDataFactory.java
deleted file mode 100644
index 05812123e..000000000
--- a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/ChildNodeDataFactory.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.fd.honeycomb.test.tools.factories;
-
-
-import com.google.common.base.Optional;
-import java.io.IOException;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.yangtools.sal.binding.generator.impl.BindingSchemaContextUtils;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
-import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ChildNodeDataFactory extends YangDataFactory {
-
- private static final Logger LOG = LoggerFactory.getLogger(ChildNodeDataFactory.class);
-
- public ChildNodeDataFactory(@Nonnull final SchemaContext schemaContext,
- @Nonnull final BindingToNormalizedNodeCodec serializer,
- @Nonnull final AbstractModuleStringInstanceIdentifierCodec iidParser) {
- super(schemaContext, serializer, iidParser);
- }
-
- public DataObject getChildNodeData(final String instanceIdentifier,
- final String resourcePath) throws DeserializationException, IOException {
- // Parse string ID into YangId
- final YangInstanceIdentifier nodeYid = iidParser.deserialize(instanceIdentifier);
- // Look for parent YangId
- final YangInstanceIdentifier parentYid = nodeYid.getParent();
-
- if (parentYid.isEmpty()) {
- throw new IllegalArgumentException(
- "Attempt to process root node as children has been detected,to process root nodes just don't use id in @InjectTestData");
- }
- // Find Schema node for parent of data that's currently being parsed (needed when parsing the data into NormalizedNodes)
- return getDataForNode(nodeYid, resourcePath, getNonRootParentSchema(parentYid));
- }
-
- private DataNodeContainer getNonRootParentSchema(final YangInstanceIdentifier parentYangId)
- throws DeserializationException {
- LOG.debug("Processing parent identifier {}", parentYangId);
- final Optional<InstanceIdentifier<? extends DataObject>> parentInstanceId = serializer.toBinding(parentYangId);
- if (!parentInstanceId.isPresent()) {
- throw new IllegalStateException("Unable to resolve " + parentYangId + " to instance identifier");
- }
-
- final Optional<DataNodeContainer> dataNodeContainerOptional =
- BindingSchemaContextUtils.findDataNodeContainer(schemaContext, parentInstanceId.get());
-
- if (!dataNodeContainerOptional.isPresent()) {
- throw new IllegalArgumentException("Error finding DataNodeContainer for " + parentInstanceId.get());
- }
-
- return dataNodeContainerOptional.get();
- }
-}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/RootNodeDataFactory.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/RootNodeDataFactory.java
deleted file mode 100644
index 3aacea016..000000000
--- a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/RootNodeDataFactory.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.fd.honeycomb.test.tools.factories;
-
-
-import java.io.IOException;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
-import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class RootNodeDataFactory extends YangDataFactory {
-
- public RootNodeDataFactory(@Nonnull final SchemaContext schemaContext,
- @Nonnull final BindingToNormalizedNodeCodec serializer,
- @Nonnull final AbstractModuleStringInstanceIdentifierCodec iidParser) {
- super(schemaContext, serializer, iidParser);
- }
-
- public DataObject getRootNodeData(final YangInstanceIdentifier rootInstanceIdentifier,
- final String resourcePath) throws DeserializationException, IOException {
- //entire schema context is parent schema in this case
- return getDataForNode(rootInstanceIdentifier, resourcePath, schemaContext);
- }
-}
diff --git a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/YangDataFactory.java b/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/YangDataFactory.java
deleted file mode 100644
index ecf556cd2..000000000
--- a/infra/test-utils/test-tools/src/main/java/io/fd/honeycomb/test/tools/factories/YangDataFactory.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package io.fd.honeycomb.test.tools.factories;
-
-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.collect.Iterables;
-import io.fd.honeycomb.translate.util.JsonUtils;
-import java.io.IOException;
-import java.util.AbstractMap;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-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.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
-import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-
-/**
- * Common logic for reading of yang data
- */
-abstract class YangDataFactory {
-
- final SchemaContext schemaContext;
- final BindingToNormalizedNodeCodec serializer;
- final AbstractModuleStringInstanceIdentifierCodec iidParser;
-
- YangDataFactory(@Nonnull final SchemaContext schemaContext,
- @Nonnull final BindingToNormalizedNodeCodec serializer,
- @Nonnull final AbstractModuleStringInstanceIdentifierCodec iidParser) {
- this.schemaContext = checkNotNull(schemaContext, "SchemaContext cannot be null");
- this.serializer = checkNotNull(serializer, "Serializer cannot be null");
- this.iidParser = checkNotNull(iidParser, "Instance identifier parser cannot be null");
- }
-
- DataObject getDataForNode(final YangInstanceIdentifier nodeYangIdentifier,
- final String resourcePath,
- final DataNodeContainer parentSchema)
- throws DeserializationException, IOException {
-
- // Reads resources from provided resource path
- final ContainerNode rootData = getCheckedRootData(resourcePath, parentSchema);
-
- // Now transform the single child from JSON into BA format
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> actualData =
- extractCheckedSingleChild(rootData);
-
- return getCheckedBinding(nodeYangIdentifier, actualData).getValue();
- }
-
- private ContainerNode getCheckedRootData(final String resourcePath, final DataNodeContainer parentSchema)
- throws IOException {
- // TODO the cast to SchemaNode is dangerous and would not work for Augments, Choices and some other nodes maybe. At least check
- // TODO not sure if this is true, while testing this code was working fine event while processing choices/cases,
- // TODO only problem is to find suitable codec that can process cases,etc
- // Transform JSON into NormalizedNode
-
- final ContainerNode rootData = JsonUtils.readJson(schemaContext,
- checkNotNull(this.getClass().getResource(resourcePath), "Unable to find resource %s", resourcePath)
- .openStream(), ((SchemaNode) parentSchema));
-
- checkArgument(rootData.getValue().size() == 1, "Only a single data node is expected in %s, but there were: %s",
- resourcePath, rootData.getValue());
- return rootData;
- }
-
- private DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> extractCheckedSingleChild(
- final ContainerNode rootData) {
- // Now transform the single child from JSON into BA format
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> actualData =
- Iterables.getFirst(rootData.getValue(), null);
-
- checkNotNull(actualData, "Unable to extract single child from %s", rootData);
- return actualData;
- }
-
- private Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> getCheckedBinding(
- final YangInstanceIdentifier nodeYangIdentifier,
- final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> actualData)
- throws DeserializationException {
- final Optional<Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject>> ba =
- serializer.toBinding(new AbstractMap.SimpleImmutableEntry<>(nodeYangIdentifier, actualData));
-
- checkArgument(ba.isPresent(), "Unable to convert to binding %s", nodeYangIdentifier);
- return ba.get();
- }
-}
diff --git a/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/AbstractYangDataProcessorTest.java b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/AbstractYangDataProcessorTest.java
new file mode 100644
index 000000000..2d5f0259d
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/AbstractYangDataProcessorTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+
+import io.fd.honeycomb.test.tools.annotations.InjectablesProcessor;
+import org.junit.Before;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.$YangModuleInfoImpl;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+
+abstract class AbstractYangDataProcessorTest implements InjectablesProcessor, YangContextProducer {
+
+ ModuleInfoBackedContext moduleInfoBackedContext;
+ AbstractModuleStringInstanceIdentifierCodec codec;
+ BindingToNormalizedNodeCodec serializer;
+
+ @Before
+ public void init() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+ moduleInfoBackedContext = provideSchemaContextFor(Collections.singleton($YangModuleInfoImpl.getInstance()));
+ codec = getIIDCodec(moduleInfoBackedContext);
+ serializer = createSerializer(moduleInfoBackedContext);
+
+ // to init children
+ setUp();
+ }
+
+ // for children init
+ abstract void setUp();
+}
diff --git a/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessorTest.java b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessorTest.java
new file mode 100644
index 000000000..e1dbc1803
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ContainerNodeDataProcessorTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import static org.junit.Assert.*;
+
+public class ContainerNodeDataProcessorTest extends AbstractYangDataProcessorTest {
+
+ private ContainerNodeDataProcessor processor;
+
+ @Override
+ void setUp() {
+ processor = new ContainerNodeDataProcessor(moduleInfoBackedContext.getSchemaContext(), serializer);
+ }
+
+ @Test
+ public void testGetNodeDataNestedContainer() {
+ final DataObject nodeData = processor.getNodeData(codec.deserialize(InjectionTestData.CONTAINER_UNDER_LIST_DATA_PATH),
+ InjectionTestData.CONTAINER_UNDER_LIST_RESOURCE);
+ assertNotNull(nodeData);
+ }
+
+ @Test
+ public void testGetNodeDataRootContainer() {
+ final DataObject nodeData = processor.getNodeData(YangInstanceIdentifier.EMPTY, InjectionTestData.CONTAINER_IN_ROOT_RESOURCE);
+ assertNotNull(nodeData);
+ }
+
+
+ @Test
+ public void testCanProcessNegative() {
+ assertFalse(processor.canProcess(codec.deserialize(InjectionTestData.SIMPLE_LIST_DATA_PATH)));
+ assertFalse(processor.canProcess(codec.deserialize(InjectionTestData.NESTED_LIST_DATA_PATH)));
+ }
+
+ @Test
+ public void testCanProcessPositive() {
+ assertTrue(processor.canProcess(YangInstanceIdentifier.EMPTY));
+ assertTrue(processor.canProcess(codec.deserialize(InjectionTestData.CONTAINER_UNDER_LIST_DATA_PATH)));
+ }
+}
diff --git a/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/HoneycombTestRunnerTest.java b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/HoneycombTestRunnerContainerTest.java
index 42de7ed4d..1461fa377 100644
--- a/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/HoneycombTestRunnerTest.java
+++ b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/HoneycombTestRunnerContainerTest.java
@@ -16,27 +16,27 @@
package io.fd.honeycomb.test.tools;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
import io.fd.honeycomb.test.tools.annotations.InjectTestData;
import io.fd.honeycomb.test.tools.annotations.InjectablesProcessor;
import io.fd.honeycomb.test.tools.annotations.SchemaContextProvider;
-import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.$YangModuleInfoImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.AugContainerAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.SimpleContainer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.SimpleContainerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.NestedContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.SimpleList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.augmented.container.ListInAugment;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.simple.list.ContUnderList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.simple.list.ContUnderListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.simple.list.NestedList;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import java.util.Collections;
+
+import static io.fd.honeycomb.test.tools.InjectionTestData.*;
+import static org.junit.Assert.*;
+
@RunWith(HoneycombTestRunner.class)
-public class HoneycombTestRunnerTest implements InjectablesProcessor {
+public class HoneycombTestRunnerContainerTest implements InjectablesProcessor {
@InjectTestData(resourcePath = "/simpleContainerEmpty.json")
private SimpleContainer simpleContainer;
@@ -52,6 +52,19 @@ public class HoneycombTestRunnerTest implements InjectablesProcessor {
"/hc-data:cont-under-list")
private ContUnderList containerUnderList;
+ @InjectTestData(resourcePath = AUGMENT_LIST_RESOURCE, id = AUGMENT_LIST_DATA_PATH)
+ private ListInAugment listInAugment;
+
+ @InjectTestData(resourcePath = NESTED_LIST_RESOURCE, id = NESTED_LIST_DATA_PATH)
+ private NestedList nestedList;
+
+ @InjectTestData(resourcePath = ROOT_LIST_RESOURCE, id = ROOT_LIST_DATA_PATH)
+ private RootList rootList;
+
+ @InjectTestData(resourcePath = SIMPLES_LIST_RESOURCE, id = SIMPLE_LIST_DATA_PATH)
+ private SimpleList simpleList;
+
+
@SchemaContextProvider
public ModuleInfoBackedContext getSchemaContext() {
return provideSchemaContextFor(Collections.singleton($YangModuleInfoImpl.getInstance()));
diff --git a/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/InjectionTestData.java b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/InjectionTestData.java
new file mode 100644
index 000000000..4d4ab5420
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/InjectionTestData.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+final class InjectionTestData {
+
+ static final String CONTAINER_UNDER_LIST_DATA_PATH = "/hc-data:simple-container" +
+ "/hc-data:simple-list[hc-data:name='nameUnderSimpleList']" +
+ "/hc-data:cont-under-list";
+
+ static final String SIMPLE_LIST_DATA_PATH = "/hc-data:simple-container" +
+ "/hc-data:simple-list[hc-data:name='nameUnderSimpleList']";
+
+ static final String NESTED_LIST_DATA_PATH = "/hc-data:simple-container" +
+ "/hc-data:simple-list[hc-data:name='nameUnderSimpleList']" +
+ "/hc-data:nested-list[hc-data:nested-name='nameUnderNestedList']";
+
+ static final String ROOT_LIST_DATA_PATH = "/hc-data:root-list[hc-data:root-name='rootName']";
+ static final String AUGMENT_LIST_DATA_PATH = "/hc-data:simple-container" +
+ "/hc-data:augmented-container" +
+ "/hc-data:list-in-augment[hc-data:key-in-augment='keyInAugment']";
+
+ static final String CONTAINER_IN_ROOT_RESOURCE = "/simpleContainerEmpty.json";
+ static final String CONTAINER_UNDER_LIST_RESOURCE = "/containerInList.json";
+ static final String SIMPLES_LIST_RESOURCE = "/simpleListEntry.json";
+ static final String NESTED_LIST_RESOURCE = "/nestedListEntry.json";
+ static final String ROOT_LIST_RESOURCE = "/rootListEntry.json";
+ static final String AUGMENT_LIST_RESOURCE = "/augmentListEntry.json";
+
+ private InjectionTestData() {
+ }
+}
diff --git a/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ListNodeDataProcessorTest.java b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ListNodeDataProcessorTest.java
new file mode 100644
index 000000000..1118d3387
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/java/io/fd/honeycomb/test/tools/ListNodeDataProcessorTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.test.tools;
+
+
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.RootList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.SimpleList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.augmented.container.ListInAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.data.rev150105.simple.container.simple.list.NestedList;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import static io.fd.honeycomb.test.tools.InjectionTestData.*;
+import static org.junit.Assert.*;
+
+public class ListNodeDataProcessorTest extends AbstractYangDataProcessorTest {
+
+ private ListNodeDataProcessor processor;
+
+ @Override
+ void setUp() {
+ processor = new ListNodeDataProcessor(moduleInfoBackedContext.getSchemaContext(), serializer);
+ }
+
+ @Test
+ public void testCanProcessPositive() {
+ assertTrue(processor.canProcess(codec.deserialize(SIMPLE_LIST_DATA_PATH)));
+ assertTrue(processor.canProcess(codec.deserialize(NESTED_LIST_DATA_PATH)));
+ }
+
+ @Test
+ public void testCanProcessNegative() {
+ assertFalse(processor.canProcess(codec.deserialize(CONTAINER_UNDER_LIST_DATA_PATH)));
+ assertFalse(processor.canProcess(YangInstanceIdentifier.EMPTY));
+ }
+
+ @Test
+ public void testGetNodeDataSimpleList() {
+ final DataObject nodeData = processor.getNodeData(codec.deserialize(SIMPLE_LIST_DATA_PATH), SIMPLES_LIST_RESOURCE);
+ assertNotNull(nodeData);
+ assertEquals("nameUnderSimpleList", ((SimpleList) nodeData).getName());
+ }
+
+ @Test
+ public void testGetNodeDataNestedList() {
+ final DataObject nodeData = processor.getNodeData(codec.deserialize(NESTED_LIST_DATA_PATH), NESTED_LIST_RESOURCE);
+ assertNotNull(nodeData);
+ assertEquals("nameUnderNestedList", ((NestedList) nodeData).getNestedName());
+ }
+
+ @Test
+ public void testGetNodeDataRootList() {
+ final DataObject nodeData = processor.getNodeData(codec.deserialize(ROOT_LIST_DATA_PATH), ROOT_LIST_RESOURCE);
+ assertNotNull(nodeData);
+ assertEquals("rootName", ((RootList) nodeData).getRootName());
+ }
+
+ @Test
+ public void testGetNodeDataAugmentList() {
+ final DataObject nodeData = processor.getNodeData(codec.deserialize(AUGMENT_LIST_DATA_PATH), AUGMENT_LIST_RESOURCE);
+ assertNotNull(nodeData);
+ assertEquals("keyInAugment", ((ListInAugment) nodeData).getKeyInAugment());
+ }
+}
diff --git a/infra/test-utils/test-tools/src/test/resources/augmentListEntry.json b/infra/test-utils/test-tools/src/test/resources/augmentListEntry.json
new file mode 100644
index 000000000..1bdc3e6e2
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/resources/augmentListEntry.json
@@ -0,0 +1,10 @@
+{
+ "list-in-augment":[
+ {
+ "key-in-augment":"keyInAugment"
+ },
+ {
+ "key-in-augment":"otherKeyInAugment"
+ }
+ ]
+} \ No newline at end of file
diff --git a/infra/test-utils/test-tools/src/test/resources/nestedListEntry.json b/infra/test-utils/test-tools/src/test/resources/nestedListEntry.json
new file mode 100644
index 000000000..c874f1c94
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/resources/nestedListEntry.json
@@ -0,0 +1,10 @@
+{
+ "nested-list": [
+ {
+ "nested-name": "nameUnderNestedList"
+ },
+ {
+ "nested-name": "otherName"
+ }
+ ]
+}
diff --git a/infra/test-utils/test-tools/src/test/resources/rootListEntry.json b/infra/test-utils/test-tools/src/test/resources/rootListEntry.json
new file mode 100644
index 000000000..cd09c685e
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/resources/rootListEntry.json
@@ -0,0 +1,10 @@
+{
+ "root-list":[
+ {
+ "root-name":"rootName"
+ },
+ {
+ "root-name":"otherRootName"
+ }
+ ]
+} \ No newline at end of file
diff --git a/infra/test-utils/test-tools/src/test/resources/simpleListEntry.json b/infra/test-utils/test-tools/src/test/resources/simpleListEntry.json
new file mode 100644
index 000000000..64ad3e6bd
--- /dev/null
+++ b/infra/test-utils/test-tools/src/test/resources/simpleListEntry.json
@@ -0,0 +1,10 @@
+{
+ "simple-list": [
+ {
+ "name": "nameUnderSimpleList"
+ },
+ {
+ "name": "otherName"
+ }
+ ]
+}
diff --git a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/JsonUtils.java b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/JsonUtils.java
index 3216cac20..332bf6767 100644
--- a/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/JsonUtils.java
+++ b/infra/translate-utils/src/main/java/io/fd/honeycomb/translate/util/JsonUtils.java
@@ -19,15 +19,10 @@ package io.fd.honeycomb.translate.util;
import com.google.common.base.Charsets;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import javax.annotation.Nonnull;
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.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
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;
@@ -44,6 +39,9 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.annotation.Nonnull;
+import java.io.*;
+
public final class JsonUtils {
private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class);
@@ -101,6 +99,43 @@ public final class JsonUtils {
return builder.build();
}
+ public static ContainerNode readContainerEntryJson(@Nonnull final SchemaContext schemaContext,
+ @Nonnull final InputStream stream,
+ @Nonnull final SchemaNode parentSchema,
+ @Nonnull final YangInstanceIdentifier.NodeIdentifier nodeIdentifier) {
+ final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> builder =
+ Builders.containerBuilder().withNodeIdentifier(nodeIdentifier);
+ final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(builder);
+
+ try (final JsonParserStream jsonParser = JsonParserStream.create(writer, schemaContext, parentSchema)) {
+ final JsonReader reader = new JsonReader(new InputStreamReader(stream, Charsets.UTF_8));
+ jsonParser.parse(reader);
+ } catch (IOException e) {
+ LOG.warn("Unable to close json parser. Ignoring exception", e);
+ }
+
+ return builder.build();
+ }
+
+ public static MapEntryNode readListEntryFromJson(@Nonnull final SchemaContext schemaContext,
+ @Nonnull final InputStream stream,
+ @Nonnull final SchemaNode parentSchema,
+ @Nonnull final YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier) {
+ final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = Builders.mapEntryBuilder()
+ .withNodeIdentifier(nodeIdentifier);
+
+
+ final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(mapEntryBuilder);
+ try (final JsonParserStream jsonParser = JsonParserStream.create(writer, schemaContext, parentSchema)) {
+ final JsonReader reader = new JsonReader(new InputStreamReader(stream, Charsets.UTF_8));
+ jsonParser.parse(reader);
+ } catch (IOException e) {
+ LOG.warn("Unable to close json parser. Ignoring exception", e);
+ }
+
+ return mapEntryBuilder.build();
+ }
+
private static void writeChildren(final NormalizedNodeWriter nnWriter, final ContainerNode data) throws IOException {
for (final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> child : data.getValue()) {
nnWriter.write(child);