summaryrefslogtreecommitdiffstats
path: root/v3po
diff options
context:
space:
mode:
authorMaros Marsalek <mmarsale@cisco.com>2016-03-17 14:29:25 +0100
committerMaros Marsalek <mmarsale@cisco.com>2016-03-22 09:47:09 +0000
commita60162e7c26a1d11976d8d78ee369b23805154aa (patch)
tree66670eedb77b03c7b88833bb27e0fbc04aa80e09 /v3po
parent8339ec66e0dfbed1411ff451846db4de8b035a32 (diff)
Address TODOs for VPP readers
Cleanup the mapping methods Clenup and document SPIs Exctract SubtreeManager interface Change-Id: Idaacebf949926107b0e4f2f467e5a4470126fa96 Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'v3po')
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ChildVppReader.java12
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReaderRegistry.java8
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/SubtreeManager.java39
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppReader.java27
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/AbstractCompositeVppReader.java87
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeChildVppReader.java36
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeListVppReader.java87
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeRootVppReader.java35
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ChildVppReaderCustomizer.java13
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ListVppReaderCustomizer.java24
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/RootVppReaderCustomizer.java18
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/DelegatingReaderRegistry.java41
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/NoopReaderCustomizer.java3
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflectionUtils.java79
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveChildReaderCustomizer.java2
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveRootReaderCustomizer.java3
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppApiReaderCustomizer.java10
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppRWUtils.java (renamed from v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppReaderUtils.java)72
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/BridgeDomainCustomizer.java50
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VersionCustomizer.java11
-rw-r--r--v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/BdTest.java56
-rw-r--r--v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/VppStateUtils.java (renamed from v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VppStateUtils.java)23
22 files changed, 477 insertions, 259 deletions
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ChildVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ChildVppReader.java
index 8f2a1ce9e..040c8fdef 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ChildVppReader.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ChildVppReader.java
@@ -24,16 +24,20 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
* Child VPP reader allowing its parent to pass the builder object
+ *
+ * @param <C> Specific DataObject derived type, that is handled by this reader
*/
@Beta
public interface ChildVppReader<C extends DataObject> extends VppReader<C> {
/**
- * Read subtree starting from node managed by this reader and place the subtree within parent builder object if
- * the data exists.
+ * Reads subtree starting from node managed by this reader and place the subtree within parent builder object if the
+ * data exists.
*
- * @param id Unique identifier pointing to the node managed by this reader. Useful when necessary to determine
- * the exact position within more complex subtrees.
+ * @param id Unique identifier pointing to the node managed by this reader. Useful when necessary to
+ * determine the exact position within more complex subtrees.
+ * @param parentBuilder Builder of parent DataObject. Objects read on this level (if any) must be placed into the
+ * parent builder.
*/
void read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
@Nonnull final Builder<? extends DataObject> parentBuilder);
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReaderRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReaderRegistry.java
index cea5c8137..54809c98e 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReaderRegistry.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ReaderRegistry.java
@@ -16,6 +16,7 @@
package io.fd.honeycomb.v3po.impl.trans;
+import com.google.common.annotations.Beta;
import java.util.List;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
@@ -23,7 +24,12 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
/**
* Simple delegating reader suitable as a holder for all other root readers, providing readAll feature
*/
+@Beta
public interface ReaderRegistry extends VppReader<DataObject> {
- @Nonnull List<? extends DataObject> readAll();
+ /**
+ * Perform read on all underlying readers and merge the results into a single list
+ */
+ @Nonnull
+ List<? extends DataObject> readAll();
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/SubtreeManager.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/SubtreeManager.java
new file mode 100644
index 000000000..0aa927cd0
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/SubtreeManager.java
@@ -0,0 +1,39 @@
+/*
+ * 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.v3po.impl.trans;
+
+import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Base identifiable subtree manager(reader, writer etc.)
+ *
+ * @param <D> Specific DataObject derived type, that is managed by this manager
+ */
+@Beta
+public interface SubtreeManager<D extends DataObject> {
+
+ /**
+ * Gets the type of node managed by this reader
+ *
+ * @return Class object for node managed by this reader
+ */
+ @Nonnull
+ InstanceIdentifier<D> getManagedDataObjectType();
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppReader.java
index 0033cfc07..c8c13f65a 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppReader.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/VppReader.java
@@ -23,10 +23,12 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
- * Base VPP reader, responsible for translation between DataObjects and VPP apis
+ * Base VPP reader, responsible for translation between DataObjects and VPP APIs
+ *
+ * @param <D> Specific DataObject derived type, that is handled by this reader
*/
@Beta
-public interface VppReader<D extends DataObject> {
+public interface VppReader<D extends DataObject> extends SubtreeManager<D> {
// TODO add vpp read context that will be shared by all readers during a single read to keep useful information
// preventing possible duplicate reads from VPP
@@ -35,21 +37,12 @@ public interface VppReader<D extends DataObject> {
/**
* Reads from VPP data identified by id
*
- * @param id unique identifier of subtree to be read.
- * The subtree must contain managed data object type enforcing it to point
- * to the node type managed by this reader or below. For identifiers pointing below
- * node managed by this reader, its reader's responsibility to filter out the right
- * node or to delegate the read to a child reader.
- *
- * @return List of DataObjects identified by id. If the ID points to a single node, it will be wrapped in a list
+ * @param id unique identifier of subtree to be read. The subtree must contain managed data object type. For
+ * identifiers pointing below node managed by this reader, it's reader's responsibility to filter out the
+ * right node or to delegate the read to a child reader.
+ * @return List of DataObjects identified by id. If the ID points to a single node, it will be wrapped in a list
*/
- @Nonnull List<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id);
-
+ @Nonnull
+ List<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id);
- /**
- * Get the type of node managed by this reader
- *
- * @return Class object for node managed by this reader
- */
- @Nonnull InstanceIdentifier<D> getManagedDataObjectType();
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/AbstractCompositeVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/AbstractCompositeVppReader.java
index 566c4fcc8..121d50dcb 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/AbstractCompositeVppReader.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/AbstractCompositeVppReader.java
@@ -18,18 +18,16 @@ package io.fd.honeycomb.v3po.impl.trans.impl;
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import io.fd.honeycomb.v3po.impl.trans.ChildVppReader;
import io.fd.honeycomb.v3po.impl.trans.VppReader;
-import io.fd.honeycomb.v3po.impl.trans.util.VppReaderUtils;
+import io.fd.honeycomb.v3po.impl.trans.util.ReflectionUtils;
+import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
@@ -50,52 +48,23 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
private final Map<Class<? extends DataObject>, ChildVppReader<? extends Augmentation<D>>> augReaders;
private final InstanceIdentifier<D> instanceIdentifier;
- public AbstractCompositeVppReader(
- final Class<D> managedDataObjectType,
+ AbstractCompositeVppReader(final Class<D> managedDataObjectType,
final List<ChildVppReader<? extends ChildOf<D>>> childReaders,
final List<ChildVppReader<? extends Augmentation<D>>> augReaders) {
- this.childReaders = childReadersToMap(childReaders);
- this.augReaders = augReadersToMap(augReaders);
+ this.childReaders = VppRWUtils.uniqueLinkedIndex(childReaders, VppRWUtils.MANAGER_CLASS_FUNCTION);
+ this.augReaders = VppRWUtils.uniqueLinkedIndex(augReaders, VppRWUtils.MANAGER_CLASS_AUG_FUNCTION);
this.instanceIdentifier = InstanceIdentifier.create(managedDataObjectType);
}
- protected final Map<Class<? extends DataObject>, ChildVppReader<? extends ChildOf<D>>> childReadersToMap(
- final List<ChildVppReader<? extends ChildOf<D>>> childReaders) {
- final LinkedHashMap<Class<? extends DataObject>, ChildVppReader<? extends ChildOf<D>>>
- classVppReaderLinkedHashMap = new LinkedHashMap<>();
-
- for (ChildVppReader<? extends ChildOf<D>> childReader : childReaders) {
- Preconditions.checkArgument(
- classVppReaderLinkedHashMap.put(childReader.getManagedDataObjectType().getTargetType(), childReader) == null,
- "Duplicate (%s) child readers detected under: %s", childReader.getManagedDataObjectType(),
- getManagedDataObjectType());
- }
-
- return classVppReaderLinkedHashMap;
- }
-
- // FIXME add child/augReaders to one list and unify toMap helper methods + move to utils
- protected final Map<Class<? extends DataObject>, ChildVppReader<? extends Augmentation<D>>> augReadersToMap(
- final List<ChildVppReader<? extends Augmentation<D>>> childReaders) {
- final LinkedHashMap<Class<? extends DataObject>, ChildVppReader<? extends Augmentation<D>>>
- classVppReaderLinkedHashMap = new LinkedHashMap<>();
-
- for (ChildVppReader<? extends DataObject> childReader : childReaders) {
- Preconditions.checkArgument(
- classVppReaderLinkedHashMap.put(childReader.getManagedDataObjectType().getTargetType(),
- (ChildVppReader<? extends Augmentation<D>>) childReader) == null,
- "Duplicate (%s) child readers detected under: %s", childReader.getManagedDataObjectType(),
- getManagedDataObjectType());
- }
- return classVppReaderLinkedHashMap;
- }
-
@Nonnull
@Override
public final InstanceIdentifier<D> getManagedDataObjectType() {
return instanceIdentifier;
}
+ /**
+ * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present.
+ */
protected List<D> readCurrent(final InstanceIdentifier<D> id) {
final B builder = getBuilder(id);
// Cache empty value to determine if anything has changed later TODO cache in a field
@@ -103,6 +72,7 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
readCurrentAttributes(id, builder);
+ // TODO expect exceptions from reader
for (ChildVppReader<? extends ChildOf<D>> child : childReaders.values()) {
child.read(id, builder);
}
@@ -132,53 +102,57 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
private List<? extends DataObject> readSubtree(final InstanceIdentifier<? extends DataObject> id) {
// Read only specific subtree
- final Class<? extends DataObject> next = VppReaderUtils.getNextId(id, getManagedDataObjectType()).getType();
+ final Class<? extends DataObject> next = VppRWUtils.getNextId(id, getManagedDataObjectType()).getType();
final ChildVppReader<? extends ChildOf<D>> vppReader = childReaders.get(next);
if (vppReader != null) {
return vppReader.read(id);
} else {
// If there's no dedicated reader, use read current
- final InstanceIdentifier<D> currentId = VppReaderUtils.cutId(id, getManagedDataObjectType());
+ final InstanceIdentifier<D> currentId = VppRWUtils.cutId(id, getManagedDataObjectType());
final List<D> current = readCurrent(currentId);
// then perform post-reading filtering (return only requested sub-node)
return current.isEmpty() ? current : filterSubtree(current, id, getManagedDataObjectType().getTargetType()) ;
}
}
- @SuppressWarnings("unchecked")
- protected InstanceIdentifier<D> getCurrentId(final InstanceIdentifier<? extends DataObject> parentId) {
- Preconditions.checkArgument(!parentId.contains(getManagedDataObjectType()),
- "Unexpected InstanceIdentifier %s, already contains %s", parentId, getManagedDataObjectType());
- final InstanceIdentifier.PathArgument t = Iterables.getOnlyElement(getManagedDataObjectType().getPathArguments());
- return (InstanceIdentifier<D>) InstanceIdentifier.create(Iterables.concat(
- parentId.getPathArguments(), Collections.singleton(t)));
- }
-
+ /**
+ * Fill in current node's attributes
+ *
+ * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present.
+ * @param builder Builder object for current node where the read attributes must be placed
+ */
protected abstract void readCurrentAttributes(final InstanceIdentifier<D> id, B builder);
- protected abstract B getBuilder(InstanceIdentifier<? extends DataObject> id);
+ /**
+ * Return new instance of a builder object for current node
+ *
+ * @param id {@link InstanceIdentifier} pointing to current node. In case of keyed list, key must be present.
+ * @return Builder object for current node type
+ */
+ protected abstract B getBuilder(InstanceIdentifier<D> id);
// TODO move filtering out of here into a dedicated Filter ifc
@Nonnull
private static List<? extends DataObject> filterSubtree(@Nonnull final List<? extends DataObject> built,
@Nonnull final InstanceIdentifier<? extends DataObject> absolutPath,
@Nonnull final Class<?> managedType) {
- // TODO is there a better way than reflection ?
+ // TODO is there a better way than reflection ? e.g. convert into NN and filter out with a utility
+ // FIXME this needs to be recursive. right now it expects only 1 additional element in ID + test
List<DataObject> filtered = Lists.newArrayList();
for (DataObject parent : built) {
final InstanceIdentifier.PathArgument nextId =
- VppReaderUtils.getNextId(absolutPath, InstanceIdentifier.create(parent.getClass()));
+ VppRWUtils.getNextId(absolutPath, InstanceIdentifier.create(parent.getClass()));
- Optional<Method> method = VppReaderUtils.findMethodReflex(managedType, "get",
+ Optional<Method> method = ReflectionUtils.findMethodReflex(managedType, "get",
Collections.<Class<?>>emptyList(), nextId.getType());
if (method.isPresent()) {
filterSingle(filtered, parent, nextId, method);
} else {
// List child nodes
- method = VppReaderUtils.findMethodReflex(managedType,
+ method = ReflectionUtils.findMethodReflex(managedType,
"get" + nextId.getType().getSimpleName(), Collections.<Class<?>>emptyList(), List.class);
if (method.isPresent()) {
@@ -204,7 +178,7 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
@Override
public boolean apply(@Nullable final DataObject input) {
final Optional<Method> keyGetter =
- VppReaderUtils.findMethodReflex(nextId.getType(), "get",
+ ReflectionUtils.findMethodReflex(nextId.getType(), "get",
Collections.<Class<?>>emptyList(), key.getClass());
final Object actualKey;
actualKey = invoke(keyGetter.get(), nextId, input);
@@ -229,5 +203,4 @@ abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builde
throw new IllegalArgumentException("Unable to get " + nextId + " from " + parent, e);
}
}
-
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeChildVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeChildVppReader.java
index 7c66695c4..e1dac48b3 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeChildVppReader.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeChildVppReader.java
@@ -20,7 +20,7 @@ import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import io.fd.honeycomb.v3po.impl.trans.ChildVppReader;
import io.fd.honeycomb.v3po.impl.trans.impl.spi.ChildVppReaderCustomizer;
-import io.fd.honeycomb.v3po.impl.trans.util.VppReaderUtils;
+import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
@@ -30,13 +30,26 @@ import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Composite implementation of {@link ChildVppReader} able to place the read result into
+ * parent builder object.
+ */
@Beta
@ThreadSafe
-public class CompositeChildVppReader<C extends DataObject, B extends Builder<C>> extends AbstractCompositeVppReader<C, B>
+public final class CompositeChildVppReader<C extends DataObject, B extends Builder<C>> extends AbstractCompositeVppReader<C, B>
implements ChildVppReader<C> {
private final ChildVppReaderCustomizer<C, B> customizer;
+ /**
+ * Create new {@link CompositeChildVppReader}
+ *
+ * @param managedDataObjectType Class object for managed data type
+ * @param childReaders Child nodes(container, list) readers
+ * @param augReaders Child augmentations readers
+ * @param customizer Customizer instance to customize this generic reader
+ *
+ */
public CompositeChildVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
@Nonnull final List<ChildVppReader<? extends Augmentation<C>>> augReaders,
@@ -45,22 +58,29 @@ public class CompositeChildVppReader<C extends DataObject, B extends Builder<C>>
this.customizer = customizer;
}
+ /**
+ * @see {@link CompositeChildVppReader#CompositeChildVppReader(Class, List, List, ChildVppReaderCustomizer)}
+ */
public CompositeChildVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
@Nonnull final ChildVppReaderCustomizer<C, B> customizer) {
- this(managedDataObjectType, childReaders, VppReaderUtils.<C>emptyAugReaderList(), customizer);
+ this(managedDataObjectType, childReaders, VppRWUtils.<C>emptyAugReaderList(), customizer);
}
+ /**
+ * @see {@link CompositeChildVppReader#CompositeChildVppReader(Class, List, List, ChildVppReaderCustomizer)}
+ */
public CompositeChildVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final ChildVppReaderCustomizer<C, B> customizer) {
- this(managedDataObjectType, VppReaderUtils.<C>emptyChildReaderList(), VppReaderUtils.<C>emptyAugReaderList(),
+ this(managedDataObjectType, VppRWUtils.<C>emptyChildReaderList(), VppRWUtils.<C>emptyAugReaderList(),
customizer);
}
@Override
public final void read(@Nonnull final InstanceIdentifier<? extends DataObject> parentId,
@Nonnull final Builder<? extends DataObject> parentBuilder) {
- final Optional<C> read = Optional.fromNullable(readCurrent(getCurrentId(parentId)).get(0));
+ final Optional<C> read = Optional.fromNullable(readCurrent(VppRWUtils.appendTypeToId(parentId,
+ getManagedDataObjectType())).get(0));
if(read.isPresent()) {
customizer.merge(parentBuilder, read.get());
@@ -69,12 +89,12 @@ public class CompositeChildVppReader<C extends DataObject, B extends Builder<C>>
@Override
protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) {
- customizer.readCurrentAttributes(builder);
+ customizer.readCurrentAttributes(id, builder);
}
@Override
- protected B getBuilder(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
- return customizer.getBuilder();
+ protected B getBuilder(@Nonnull final InstanceIdentifier<C> id) {
+ return customizer.getBuilder(id);
}
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeListVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeListVppReader.java
index f280fdb76..d64a83ccc 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeListVppReader.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeListVppReader.java
@@ -16,15 +16,15 @@
package io.fd.honeycomb.v3po.impl.trans.impl;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import io.fd.honeycomb.v3po.impl.trans.ChildVppReader;
import io.fd.honeycomb.v3po.impl.trans.impl.spi.ListVppReaderCustomizer;
-import io.fd.honeycomb.v3po.impl.trans.util.VppReaderUtils;
-import java.util.Collections;
+import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
@@ -36,13 +36,29 @@ import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Composite implementation of {@link ChildVppReader} able to place the read result into
+ * parent builder object intended for list node type.
+ *
+ * This reader checks if the IDs are wildcarded in which case it performs read of all
+ * list entries. In case the ID has a key, it reads only the specified value.
+ */
@Beta
@ThreadSafe
public final class CompositeListVppReader<C extends DataObject & Identifiable<K>, K extends Identifier<C>, B extends Builder<C>>
extends AbstractCompositeVppReader<C, B> implements ChildVppReader<C> {
- private ListVppReaderCustomizer<C, K, B> customizer;
-
+ private final ListVppReaderCustomizer<C, K, B> customizer;
+
+ /**
+ * Create new {@link CompositeListVppReader}
+ *
+ * @param managedDataObjectType Class object for managed data type. Must come from a list node type.
+ * @param childReaders Child nodes(container, list) readers
+ * @param augReaders Child augmentations readers
+ * @param customizer Customizer instance to customize this generic reader
+ *
+ */
public CompositeListVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
@Nonnull final List<ChildVppReader<? extends Augmentation<C>>> augReaders,
@@ -51,60 +67,51 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K>
this.customizer = customizer;
}
+ /**
+ * @see {@link CompositeListVppReader#CompositeListVppReader(Class, List, List, ListVppReaderCustomizer)}
+ */
public CompositeListVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
@Nonnull final ListVppReaderCustomizer<C, K, B> customizer) {
- this(managedDataObjectType, childReaders, VppReaderUtils.<C>emptyAugReaderList(), customizer);
+ this(managedDataObjectType, childReaders, VppRWUtils.<C>emptyAugReaderList(), customizer);
}
+ /**
+ * @see {@link CompositeListVppReader#CompositeListVppReader(Class, List, List, ListVppReaderCustomizer)}
+ */
public CompositeListVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final ListVppReaderCustomizer<C, K, B> customizer) {
- this(managedDataObjectType, VppReaderUtils.<C>emptyChildReaderList(), VppReaderUtils.<C>emptyAugReaderList(),
+ this(managedDataObjectType, VppRWUtils.<C>emptyChildReaderList(), VppRWUtils.<C>emptyAugReaderList(),
customizer);
}
@Override
protected List<C> readCurrent(@Nonnull final InstanceIdentifier<C> id) {
- if(shouldReadAll(id)) {
- return readList(id);
- }
- return super.readCurrent(id);
+ return shouldReadAll(id) ? readList(id) : super.readCurrent(id);
}
@Override
public void read(@Nonnull final InstanceIdentifier<? extends DataObject> id,
@Nonnull final Builder<? extends DataObject> parentBuilder) {
- final InstanceIdentifier<C> currentId = getCurrentId(id);
-
- final List<C> ifcs;
- if (shouldReadAll(id)) {
- ifcs = readList(currentId);
- } else {
- final Optional<? extends DataObject> readSingle = Optional.fromNullable(read(id).get(0));
- final Optional<C> read = readSingle.transform(new Function<DataObject, C>() {
- @Override
- public C apply(final DataObject input) {
- Preconditions.checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(input.getClass()));
- return getManagedDataObjectType().getTargetType().cast(input);
- }
- });
- ifcs = read.isPresent() ? Collections.singletonList(read.get()) : Collections.<C>emptyList();
- }
-
+ // Create ID pointing to current node
+ final InstanceIdentifier<C> currentId = VppRWUtils.appendTypeToId(id, getManagedDataObjectType());
+ // Read all, since current ID is definitely wildcarded
+ final List<C> ifcs = readList(currentId);
customizer.merge(parentBuilder, ifcs);
}
private List<C> readList(@Nonnull final InstanceIdentifier<C> id) {
- Preconditions.checkArgument(id.getTargetType().equals(getManagedDataObjectType().getTargetType()),
- "Id %s does not contain expected type %s", id, getManagedDataObjectType());
-
- return Lists.transform(customizer.getAllIds(id), new Function<InstanceIdentifier<? extends DataObject>, C>() {
+ return Lists.transform(customizer.getAllIds(id), new Function<K, C>() {
@Override
- public C apply(final InstanceIdentifier<? extends DataObject> input) {
- final List<? extends DataObject> read = read(input);
- Preconditions.checkState(read.size() == 1);
- Preconditions.checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(read.get(0).getClass()));
- return getManagedDataObjectType().getTargetType().cast(read.get(0));
+ public C apply(final K key) {
+ final InstanceIdentifier.IdentifiableItem<C, K> currentBdItem =
+ VppRWUtils.getCurrentIdItem(id, key);
+ final InstanceIdentifier<C> keyedId = VppRWUtils.replaceLastInId(id, currentBdItem);
+ final List<? extends DataObject> read = read(keyedId);
+ checkState(read.size() == 1);
+ final DataObject singleItem = read.get(0);
+ checkArgument(getManagedDataObjectType().getTargetType().isAssignableFrom(singleItem.getClass()));
+ return getManagedDataObjectType().getTargetType().cast(singleItem);
}
});
}
@@ -120,8 +127,8 @@ public final class CompositeListVppReader<C extends DataObject & Identifiable<K>
}
@Override
- protected B getBuilder(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
- return customizer.getBuilder(id.firstKeyOf(getManagedDataObjectType().getTargetType()));
+ protected B getBuilder(@Nonnull final InstanceIdentifier<C> id) {
+ return customizer.getBuilder(id);
}
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeRootVppReader.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeRootVppReader.java
index 605f1b628..1e6b7e93a 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeRootVppReader.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeRootVppReader.java
@@ -20,7 +20,7 @@ import com.google.common.annotations.Beta;
import io.fd.honeycomb.v3po.impl.trans.ChildVppReader;
import io.fd.honeycomb.v3po.impl.trans.VppReader;
import io.fd.honeycomb.v3po.impl.trans.impl.spi.RootVppReaderCustomizer;
-import io.fd.honeycomb.v3po.impl.trans.util.VppReaderUtils;
+import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
@@ -30,6 +30,9 @@ import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Composite implementation of {@link VppReader}
+ */
@Beta
@ThreadSafe
public final class CompositeRootVppReader<C extends DataObject, B extends Builder<C>> extends AbstractCompositeVppReader<C, B>
@@ -37,35 +40,49 @@ public final class CompositeRootVppReader<C extends DataObject, B extends Builde
private final RootVppReaderCustomizer<C, B> customizer;
+ /**
+ * Create new {@link CompositeRootVppReader}
+ *
+ * @param managedDataObjectType Class object for managed data type
+ * @param childReaders Child nodes(container, list) readers
+ * @param augReaders Child augmentations readers
+ * @param customizer Customizer instance to customize this generic reader
+ *
+ */
public CompositeRootVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
- @Nonnull final List<ChildVppReader<? extends Augmentation<C>>> childAugReaders,
+ @Nonnull final List<ChildVppReader<? extends Augmentation<C>>> augReaders,
@Nonnull final RootVppReaderCustomizer<C, B> customizer) {
- super(managedDataObjectType, childReaders, childAugReaders);
+ super(managedDataObjectType, childReaders, augReaders);
this.customizer = customizer;
}
+ /**
+ * @see {@link CompositeRootVppReader#CompositeRootVppReader(Class, List, List, RootVppReaderCustomizer)}
+ */
public CompositeRootVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
@Nonnull final RootVppReaderCustomizer<C, B> customizer) {
- this(managedDataObjectType, childReaders, VppReaderUtils.<C>emptyAugReaderList(), customizer);
+ this(managedDataObjectType, childReaders, VppRWUtils.<C>emptyAugReaderList(), customizer);
}
+ /**
+ * @see {@link CompositeRootVppReader#CompositeRootVppReader(Class, List, List, RootVppReaderCustomizer)}
+ */
public CompositeRootVppReader(@Nonnull final Class<C> managedDataObjectType,
@Nonnull final RootVppReaderCustomizer<C, B> customizer) {
- this(managedDataObjectType, VppReaderUtils.<C>emptyChildReaderList(), VppReaderUtils.<C>emptyAugReaderList(),
+ this(managedDataObjectType, VppRWUtils.<C>emptyChildReaderList(), VppRWUtils.<C>emptyAugReaderList(),
customizer);
}
@Override
protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) {
- customizer.readCurrentAttributes(builder);
+ customizer.readCurrentAttributes(id, builder);
}
@Override
- protected B getBuilder(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
- // TODO instantiate builder from customizer(as is) or reflection ?
- return customizer.getBuilder();
+ protected B getBuilder(@Nonnull final InstanceIdentifier<C> id) {
+ return customizer.getBuilder(id);
}
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ChildVppReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ChildVppReaderCustomizer.java
index 7cf0b60f6..29cfe3eeb 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ChildVppReaderCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ChildVppReaderCustomizer.java
@@ -17,13 +17,22 @@
package io.fd.honeycomb.v3po.impl.trans.impl.spi;
import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataObject;
+/**
+ * io.fd.honeycomb.v3po.impl.trans.impl.CompositeChildVppReader SPI to customize its behavior
+ */
@Beta
public interface ChildVppReaderCustomizer<C extends DataObject, B extends Builder<C>> extends
RootVppReaderCustomizer<C, B> {
- // FIXME need to capture parent builder type, but that's a inconvenient
- void merge(Builder<? extends DataObject> parentBuilder, C readValue);
+ // FIXME need to capture parent builder type, but that's inconvenient at best, is it ok to leave it Builder<?> and
+ // cast in specific customizers ? ... probably better than adding another type parameter
+
+ /**
+ * Merge read data into provided parent builder
+ */
+ void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final C readValue);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ListVppReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ListVppReaderCustomizer.java
index 855e8488d..8a6812dd6 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ListVppReaderCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ListVppReaderCustomizer.java
@@ -18,20 +18,30 @@ package io.fd.honeycomb.v3po.impl.trans.impl.spi;
import com.google.common.annotations.Beta;
import java.util.List;
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * io.fd.honeycomb.v3po.impl.trans.impl.CompositeListVppReader SPI to customize its behavior
+ */
@Beta
-public interface ListVppReaderCustomizer<C extends DataObject & Identifiable<K>, K extends Identifier<C>, B extends Builder<C>> {
-
- void readCurrentAttributes(final InstanceIdentifier<C> id, B builder);
-
- B getBuilder(K id);
+public interface ListVppReaderCustomizer<C extends DataObject & Identifiable<K>, K extends Identifier<C>, B extends Builder<C>>
+ extends RootVppReaderCustomizer<C, B> {
- List<InstanceIdentifier<C>> getAllIds(InstanceIdentifier<C> id);
+ /**
+ * Return list with IDs of all list nodes to be read.
+ *
+ * @param id wildcarded ID pointing to list node managed by enclosing reader
+ */
+ @Nonnull
+ List<K> getAllIds(@Nonnull final InstanceIdentifier<C> id);
- void merge(Builder<?> builder, List<C> currentBuilder);
+ /**
+ * Merge read data into provided parent builder
+ */
+ void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<C> readData);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/RootVppReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/RootVppReaderCustomizer.java
index fe09220d2..463e4f9d6 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/RootVppReaderCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/RootVppReaderCustomizer.java
@@ -17,13 +17,27 @@
package io.fd.honeycomb.v3po.impl.trans.impl.spi;
import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * io.fd.honeycomb.v3po.impl.trans.impl.CompositeRootVppReader SPI to customize its behavior
+ */
@Beta
public interface RootVppReaderCustomizer<C extends DataObject, B extends Builder<C>> {
- B getBuilder();
+ // TODO add (un)checked, well defined exception here to indicate issues in the customizer
+
+ /**
+ * Create new builder that will be used to build read value
+ */
+ @Nonnull
+ B getBuilder(@Nonnull final InstanceIdentifier<C> id);
- void readCurrentAttributes(B builder);
+ /**
+ * Add current data (identified by id) to the provided builder
+ */
+ void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder);
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/DelegatingReaderRegistry.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/DelegatingReaderRegistry.java
index 0aeda896a..5225bab63 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/DelegatingReaderRegistry.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/DelegatingReaderRegistry.java
@@ -16,42 +16,41 @@
package io.fd.honeycomb.v3po.impl.trans.util;
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
import io.fd.honeycomb.v3po.impl.trans.ReaderRegistry;
import io.fd.honeycomb.v3po.impl.trans.VppReader;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+/**
+ * Simple reader registry able to perform and aggregated read (ROOT read) on top of all
+ * provided readers. Also able to delegate a specific read to one of the delegate readers.
+ *
+ * This could serve as a utility to hold & hide all available readers in upper layers.
+ */
public final class DelegatingReaderRegistry implements ReaderRegistry {
private final Map<Class<? extends DataObject>, VppReader<? extends DataObject>> rootReaders;
+ /**
+ * Create new {@link DelegatingReaderRegistry}
+ *
+ * @param rootReaders List of delegate readers
+ */
public DelegatingReaderRegistry(@Nonnull final List<VppReader<? extends DataObject>> rootReaders) {
- this.rootReaders = toMap(rootReaders);
- }
-
- private static Map<Class<? extends DataObject>, VppReader<? extends DataObject>> toMap(
- final List<VppReader<? extends DataObject>> rootReaders) {
- return Maps
- .uniqueIndex(rootReaders, new Function<VppReader<? extends DataObject>, Class<? extends DataObject>>() {
- @Override
- public Class<? extends DataObject> apply(final VppReader<? extends DataObject> input) {
- return input.getManagedDataObjectType().getTargetType();
- }
- });
+ this.rootReaders = VppRWUtils.uniqueLinkedIndex(checkNotNull(rootReaders), VppRWUtils.MANAGER_CLASS_FUNCTION);
}
@Override
@Nonnull
public List<? extends DataObject> readAll() {
- final List<DataObject> objects = Lists.newArrayListWithExpectedSize(rootReaders.size());
+ final List<DataObject> objects = new ArrayList<>(rootReaders.size());
for (VppReader<? extends DataObject> rootReader : rootReaders.values()) {
final List<? extends DataObject> read = rootReader.read(rootReader.getManagedDataObjectType());
objects.addAll(read);
@@ -62,14 +61,18 @@ public final class DelegatingReaderRegistry implements ReaderRegistry {
@Nonnull
@Override
public List<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
- final InstanceIdentifier.PathArgument first = Preconditions.checkNotNull(
+ final InstanceIdentifier.PathArgument first = checkNotNull(
Iterables.getFirst(id.getPathArguments(), null), "Empty id");
final VppReader<? extends DataObject> vppReader = rootReaders.get(first.getType());
- Preconditions.checkNotNull(vppReader,
+ checkNotNull(vppReader,
"Unable to read %s. Missing reader. Current readers for: %s", id, rootReaders.keySet());
return vppReader.read(id);
}
+ /**
+ * @throws UnsupportedOperationException This getter is not supported for reader registry since it does not manage a
+ * specific node type
+ */
@Nonnull
@Override
public InstanceIdentifier<DataObject> getManagedDataObjectType() {
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/NoopReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/NoopReaderCustomizer.java
index 050f7171f..b485a6db4 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/NoopReaderCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/NoopReaderCustomizer.java
@@ -19,11 +19,12 @@ package io.fd.honeycomb.v3po.impl.trans.util;
import io.fd.honeycomb.v3po.impl.trans.impl.spi.RootVppReaderCustomizer;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public abstract class NoopReaderCustomizer<C extends DataObject, B extends Builder<C>> implements RootVppReaderCustomizer<C, B> {
@Override
- public void readCurrentAttributes(final B builder) {
+ public void readCurrentAttributes(InstanceIdentifier<C> id, final B builder) {
// Noop
}
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflectionUtils.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflectionUtils.java
new file mode 100644
index 000000000..6602d750d
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflectionUtils.java
@@ -0,0 +1,79 @@
+/*
+ * 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.v3po.impl.trans.util;
+
+import com.google.common.base.Optional;
+import java.lang.reflect.Method;
+import java.util.List;
+import javax.annotation.Nonnull;
+
+/**
+ * Reflection based utilities
+ */
+public final class ReflectionUtils {
+
+ private ReflectionUtils() {}
+
+ /**
+ * Find a specific method using reflection
+ *
+ * @param managedType Class object to find method in
+ * @param prefix Method name prefix used when finding the method. Case does not matter.
+ * @param paramTypes List of input argument types
+ * @param retType Return type
+ *
+ * @return Found method or Optional.absent() if there's no such method
+ */
+ @Nonnull
+ public static Optional<Method> findMethodReflex(@Nonnull final Class<?> managedType,
+ @Nonnull final String prefix,
+ @Nonnull final List<Class<?>> paramTypes,
+ @Nonnull final Class<?> retType) {
+ for (Method method : managedType.getMethods()) {
+ if(isMethodMatch(prefix, paramTypes, retType, method)) {
+ return Optional.of(method);
+ }
+ }
+
+ return Optional.absent();
+ }
+
+ private static boolean isMethodMatch(final @Nonnull String prefix,
+ final @Nonnull List<Class<?>> paramTypes,
+ final @Nonnull Class<?> retType, final Method method) {
+ if (!method.getName().toLowerCase().startsWith(prefix.toLowerCase())) {
+ return false;
+ }
+
+ final Class<?>[] parameterTypes = method.getParameterTypes();
+ if (parameterTypes.length != paramTypes.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < parameterTypes.length; i++) {
+ if (!parameterTypes[i].isAssignableFrom(paramTypes.get(i))) {
+ return false;
+ }
+ }
+
+ if (!method.getReturnType().equals(retType)) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveChildReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveChildReaderCustomizer.java
index 28a44eb07..d67a3afbb 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveChildReaderCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveChildReaderCustomizer.java
@@ -41,7 +41,7 @@ public class ReflexiveChildReaderCustomizer<C extends DataObject, B extends Buil
@Override
public void merge(final Builder<? extends DataObject> parentBuilder, final C readValue) {
final Optional<Method> method =
- VppReaderUtils.findMethodReflex(parentBuilder.getClass(), "set",
+ ReflectionUtils.findMethodReflex(parentBuilder.getClass(), "set",
Collections.<Class<?>>singletonList(readValue.getClass()), parentBuilder.getClass());
Preconditions.checkArgument(method.isPresent(), "Unable to set %s to %s", readValue, parentBuilder);
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveRootReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveRootReaderCustomizer.java
index 2a98bbe5b..2568f9886 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveRootReaderCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveRootReaderCustomizer.java
@@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.trans.util;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
* Might be slow !
@@ -31,7 +32,7 @@ public class ReflexiveRootReaderCustomizer<C extends DataObject, B extends Build
}
@Override
- public B getBuilder() {
+ public B getBuilder(InstanceIdentifier<C> id) {
try {
return builderClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppApiReaderCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppApiReaderCustomizer.java
index 584c7823f..1ca898c8c 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppApiReaderCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppApiReaderCustomizer.java
@@ -18,15 +18,23 @@ package io.fd.honeycomb.v3po.impl.trans.util;
import com.google.common.annotations.Beta;
+/**
+ * Abstract utility to hold the vppApi reference.
+ */
@Beta
public abstract class VppApiReaderCustomizer {
private final org.openvpp.vppjapi.vppApi vppApi;
- public VppApiReaderCustomizer(final org.openvpp.vppjapi.vppApi vppApi) {
+ protected VppApiReaderCustomizer(final org.openvpp.vppjapi.vppApi vppApi) {
this.vppApi = vppApi;
}
+ /**
+ * Get vppApi reference
+ *
+ * @return vppApi reference
+ */
public org.openvpp.vppjapi.vppApi getVppApi() {
return vppApi;
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppReaderUtils.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppRWUtils.java
index 07c54ae90..1cc0dfe92 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppReaderUtils.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppRWUtils.java
@@ -16,14 +16,17 @@
package io.fd.honeycomb.v3po.impl.trans.util;
-import com.google.common.base.Optional;
+import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
import io.fd.honeycomb.v3po.impl.trans.ChildVppReader;
-import java.lang.reflect.Method;
+import io.fd.honeycomb.v3po.impl.trans.SubtreeManager;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.ChildOf;
@@ -32,9 +35,9 @@ import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-public final class VppReaderUtils {
+public final class VppRWUtils {
- private VppReaderUtils() {}
+ private VppRWUtils() {}
/**
* Find next item in ID after provided type
@@ -77,7 +80,7 @@ public final class VppReaderUtils {
*/
@SuppressWarnings("unchecked")
@Nonnull
- public static <D extends DataObject & Identifiable<K>, K extends Identifier<D>> InstanceIdentifier<D> getCurrentId(
+ public static <D extends DataObject & Identifiable<K>, K extends Identifier<D>> InstanceIdentifier<D> replaceLastInId(
@Nonnull final InstanceIdentifier<D> id, final InstanceIdentifier.IdentifiableItem<D, K> currentBdItem) {
final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
@@ -116,37 +119,46 @@ public final class VppReaderUtils {
}
/**
- * Find a specific method using reflection
+ * Create a map from a collection, checking for duplicity in the process
*/
@Nonnull
- public static Optional<Method> findMethodReflex(@Nonnull final Class<?> managedType,
- @Nonnull final String prefix,
- @Nonnull final List<Class<?>> paramTypes,
- @Nonnull final Class<?> retType) {
- top:
- for (Method method : managedType.getMethods()) {
- if (!method.getName().toLowerCase().startsWith(prefix.toLowerCase())) {
- continue;
- }
-
- final Class<?>[] parameterTypes = method.getParameterTypes();
- if (parameterTypes.length != paramTypes.size()) {
- continue;
- }
+ public static <K, V> Map<K, V> uniqueLinkedIndex(@Nonnull final Collection<V> values, @Nonnull final Function<? super V, K> keyFunction) {
+ final Map<K, V> objectObjectLinkedHashMap = Maps.newLinkedHashMap();
+ for (V value : values) {
+ final K key = keyFunction.apply(value);
+ Preconditions.checkArgument(objectObjectLinkedHashMap.put(key, value) == null,
+ "Duplicate key detected : %s", key);
+ }
+ return objectObjectLinkedHashMap;
+ }
- for (int i = 0; i < parameterTypes.length; i++) {
- if (!parameterTypes[i].isAssignableFrom(paramTypes.get(i))) {
- continue top;
- }
- }
+ public static final Function<SubtreeManager<? extends DataObject>, Class<? extends DataObject>>
+ MANAGER_CLASS_FUNCTION = new Function<SubtreeManager<? extends DataObject>, Class<? extends DataObject>>() {
+ @Override
+ public Class<? extends DataObject> apply(final SubtreeManager<? extends DataObject> input) {
+ return input.getManagedDataObjectType().getTargetType();
+ }
+ };
- if (!method.getReturnType().equals(retType)) {
- continue;
- }
+ public static final Function<SubtreeManager<? extends Augmentation<?>>, Class<? extends DataObject>>
+ MANAGER_CLASS_AUG_FUNCTION = new Function<SubtreeManager<? extends Augmentation<?>>, Class<? extends DataObject>>() {
- return Optional.of(method);
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class<? extends DataObject> apply(final SubtreeManager<? extends Augmentation<?>> input) {
+ final Class<? extends Augmentation<?>> targetType = input.getManagedDataObjectType().getTargetType();
+ Preconditions.checkArgument(DataObject.class.isAssignableFrom(targetType));
+ return (Class<? extends DataObject>) targetType;
}
+ };
- return Optional.absent();
+ @SuppressWarnings("unchecked")
+ public static <D extends DataObject> InstanceIdentifier<D> appendTypeToId(
+ final InstanceIdentifier<? extends DataObject> parentId, final InstanceIdentifier<D> type) {
+ Preconditions.checkArgument(!parentId.contains(type),
+ "Unexpected InstanceIdentifier %s, already contains %s", parentId, type);
+ final InstanceIdentifier.PathArgument t = Iterables.getOnlyElement(type.getPathArguments());
+ return (InstanceIdentifier<D>) InstanceIdentifier.create(Iterables.concat(
+ parentId.getPathArguments(), Collections.singleton(t)));
}
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/BridgeDomainCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/BridgeDomainCustomizer.java
index 447f8509c..97d1867c2 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/BridgeDomainCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/BridgeDomainCustomizer.java
@@ -19,8 +19,9 @@ package io.fd.honeycomb.v3po.impl.vppstate;
import com.google.common.collect.Lists;
import io.fd.honeycomb.v3po.impl.trans.impl.spi.ListVppReaderCustomizer;
import io.fd.honeycomb.v3po.impl.trans.util.VppApiReaderCustomizer;
-import io.fd.honeycomb.v3po.impl.trans.util.VppReaderUtils;
+import java.util.ArrayList;
import java.util.List;
+import javax.annotation.Nonnull;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomainsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomain;
@@ -32,6 +33,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2Fib;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2FibBuilder;
import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.openvpp.vppjapi.vppBridgeDomainDetails;
import org.openvpp.vppjapi.vppBridgeDomainInterfaceDetails;
@@ -40,27 +42,19 @@ import org.openvpp.vppjapi.vppL2Fib;
public final class BridgeDomainCustomizer extends VppApiReaderCustomizer
implements ListVppReaderCustomizer<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> {
- public BridgeDomainCustomizer(final org.openvpp.vppjapi.vppApi vppApi) {
+ public BridgeDomainCustomizer(@Nonnull final org.openvpp.vppjapi.vppApi vppApi) {
super(vppApi);
}
@Override
- public void readCurrentAttributes(final InstanceIdentifier<BridgeDomain> id,
- final BridgeDomainBuilder builder) {
+ public void readCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
+ @Nonnull final BridgeDomainBuilder builder) {
final BridgeDomainKey key = id.firstKeyOf(id.getTargetType());
- final int bdId;
- try {
- bdId = Integer.parseInt(key.getName());
- } catch (NumberFormatException e) {
- // LOG.warn("Invalid key", e);
- return;
- }
+ // TODO find out if bd exists based on name and if not return
+
+ final int bdId = getVppApi().bridgeDomainIdFromName(key.getName());
final vppBridgeDomainDetails bridgeDomainDetails = getVppApi().getBridgeDomainDetails(bdId);
- // FIXME, the problem here is that while going to VPP, the id for vbd is integer ID
- // However in the models vbd's key is the name
- // And you can get vbd name from vbd's ID using vppAPI, but not the other way around, making the API hard to use
- // TO solve it, we need to store the vbd ID <-> vbd Name mapping in the (not-yet-available) read context and use it here
builder.setName(key.getName());
// builder.setName(bridgeDomainDetails.name);
builder.setArpTermination(bridgeDomainDetails.arpTerm);
@@ -99,7 +93,7 @@ public final class BridgeDomainCustomizer extends VppApiReaderCustomizer
}
private List<Interface> getIfcs(final vppBridgeDomainDetails bridgeDomainDetails) {
- final List<Interface> ifcs = Lists.newArrayListWithExpectedSize(bridgeDomainDetails.interfaces.length);
+ final List<Interface> ifcs = new ArrayList<>(bridgeDomainDetails.interfaces.length);
for (vppBridgeDomainInterfaceDetails anInterface : bridgeDomainDetails.interfaces) {
ifcs.add(new InterfaceBuilder()
.setBridgedVirtualInterface(bridgeDomainDetails.bviInterfaceName.equals(anInterface.interfaceName))
@@ -110,27 +104,29 @@ public final class BridgeDomainCustomizer extends VppApiReaderCustomizer
return ifcs;
}
+ @Nonnull
@Override
- public BridgeDomainBuilder getBuilder(final BridgeDomainKey id) {
+ public BridgeDomainBuilder getBuilder(@Nonnull final InstanceIdentifier<BridgeDomain> id) {
return new BridgeDomainBuilder();
}
+ @Nonnull
@Override
- public List<InstanceIdentifier<BridgeDomain>> getAllIds(final InstanceIdentifier<BridgeDomain> id) {
- final int[] ints = getVppApi().bridgeDomainDump(-1);
- final List<InstanceIdentifier<BridgeDomain>> allIds = Lists.newArrayListWithExpectedSize(ints.length);
- for (int i : ints) {
- final InstanceIdentifier.IdentifiableItem<BridgeDomain, BridgeDomainKey> currentBdItem =
- VppReaderUtils.getCurrentIdItem(id, new BridgeDomainKey(Integer.toString(i)));
- final InstanceIdentifier<BridgeDomain> e = VppReaderUtils.getCurrentId(id, currentBdItem);
- allIds.add(e);
+ public List<BridgeDomainKey> getAllIds(@Nonnull final InstanceIdentifier<BridgeDomain> id) {
+ final int[] bIds = getVppApi().bridgeDomainDump(-1);
+ final List<BridgeDomainKey> allIds = new ArrayList<>(bIds.length);
+ for (int bId : bIds) {
+ // FIXME this is highly inefficient having to dump all of the bridge domain details
+ final vppBridgeDomainDetails bridgeDomainDetails = getVppApi().getBridgeDomainDetails(bId);
+ final String bName = bridgeDomainDetails.name;
+ allIds.add(new BridgeDomainKey(bName));
}
return allIds;
}
@Override
- public void merge(final Builder<?> builder, final List<BridgeDomain> currentBuilder) {
- ((BridgeDomainsBuilder) builder).setBridgeDomain(currentBuilder);
+ public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<BridgeDomain> readData) {
+ ((BridgeDomainsBuilder) builder).setBridgeDomain(readData);
}
}
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VersionCustomizer.java b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VersionCustomizer.java
index 3ba21bbfb..641d61805 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VersionCustomizer.java
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VersionCustomizer.java
@@ -18,33 +18,36 @@ package io.fd.honeycomb.v3po.impl.vppstate;
import io.fd.honeycomb.v3po.impl.trans.impl.spi.ChildVppReaderCustomizer;
import io.fd.honeycomb.v3po.impl.trans.util.VppApiReaderCustomizer;
+import javax.annotation.Nonnull;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppStateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.Version;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.VersionBuilder;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.openvpp.vppjapi.vppVersion;
public final class VersionCustomizer
extends VppApiReaderCustomizer
implements ChildVppReaderCustomizer<Version, VersionBuilder> {
- public VersionCustomizer(final org.openvpp.vppjapi.vppApi vppApi) {
+ public VersionCustomizer(@Nonnull final org.openvpp.vppjapi.vppApi vppApi) {
super(vppApi);
}
@Override
- public void merge(final Builder<? extends DataObject> parentBuilder, final Version readValue) {
+ public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final Version readValue) {
((VppStateBuilder) parentBuilder).setVersion(readValue);
}
+ @Nonnull
@Override
- public VersionBuilder getBuilder() {
+ public VersionBuilder getBuilder(@Nonnull InstanceIdentifier<Version> id) {
return new VersionBuilder();
}
@Override
- public void readCurrentAttributes(final VersionBuilder builder) {
+ public void readCurrentAttributes(@Nonnull InstanceIdentifier<Version> id, @Nonnull final VersionBuilder builder) {
final vppVersion vppVersion = getVppApi().getVppVersion();
builder.setBranch(vppVersion.gitBranch);
builder.setName(vppVersion.programName);
diff --git a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/BdTest.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/BdTest.java
index ab3f6e054..7439bcd30 100644
--- a/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/BdTest.java
+++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/BdTest.java
@@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.impl.vppstate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyString;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@@ -27,9 +28,12 @@ import io.fd.honeycomb.v3po.impl.trans.util.DelegatingReaderRegistry;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppStateBuilder;
@@ -63,19 +67,46 @@ public class BdTest {
private CompositeRootVppReader<VppState, VppStateBuilder> vppStateReader;
private DelegatingReaderRegistry readerRegistry;
private vppBridgeDomainDetails bdDetails;
+ private vppBridgeDomainDetails bdDetails2;
@Before
public void setUp() throws Exception {
api = PowerMockito.mock(vppApi.class);
bdDetails = new vppBridgeDomainDetails();
-
setIfcs(bdDetails);
- setBaseAttrs(bdDetails);
+ setBaseAttrs(bdDetails, "bdn1", 1);
+
+ bdDetails2 = new vppBridgeDomainDetails();
+ setIfcs(bdDetails2);
+ setBaseAttrs(bdDetails2, "bdn2", 2);
final vppL2Fib[] l2Fibs = getL2Fibs();
PowerMockito.doReturn(l2Fibs).when(api).l2FibTableDump(Matchers.anyInt());
- PowerMockito.doReturn(bdDetails).when(api).getBridgeDomainDetails(Matchers.anyInt());
+ PowerMockito.doAnswer(new Answer<vppBridgeDomainDetails>() {
+
+ @Override
+ public vppBridgeDomainDetails answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ final Integer idx = (Integer) invocationOnMock.getArguments()[0];
+ switch (idx) {
+ case 1 : return bdDetails;
+ case 2 : return bdDetails2;
+ default: return null;
+ }
+ }
+ }).when(api).getBridgeDomainDetails(Matchers.anyInt());
+
+ PowerMockito.doAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
+ final String name = (String) invocationOnMock.getArguments()[0];
+ switch (name) {
+ case "bdn1" : return 1;
+ case "bdn2" : return 2;
+ default: return null;
+ }
+ }
+ }).when(api).bridgeDomainIdFromName(anyString());
PowerMockito.doReturn(new int[] {1, 2}).when(api).bridgeDomainDump(Matchers.anyInt());
PowerMockito.doReturn(VERSION).when(api).getVppVersion();
vppStateReader = VppStateUtils.getVppStateReader(api);
@@ -96,10 +127,10 @@ public class BdTest {
bdDetails.interfaces = new vppBridgeDomainInterfaceDetails[] {ifcDetails};
}
- private void setBaseAttrs(final vppBridgeDomainDetails bdDetails) {
- bdDetails.name = "bdn";
+ private void setBaseAttrs(final vppBridgeDomainDetails bdDetails, final String bdn, final int i) {
+ bdDetails.name = bdn;
bdDetails.arpTerm = true;
- bdDetails.bdId = 1;
+ bdDetails.bdId = i;
bdDetails.bviInterfaceName = "ifc";
bdDetails.flood = true;
bdDetails.forward = true;
@@ -154,7 +185,7 @@ public class BdTest {
// Deep child without a dedicated reader with specific l2fib key
List<? extends DataObject> read =
readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
- BridgeDomain.class, new BridgeDomainKey("1"))
+ BridgeDomain.class, new BridgeDomainKey("bdn1"))
.child(L2Fib.class, new L2FibKey(new PhysAddress("01:02:03:04:05:06"))));
// System.err.println(read);
assertEquals(read.size(), 1);
@@ -162,7 +193,7 @@ public class BdTest {
// non existing l2fib
read =
readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
- BridgeDomain.class, new BridgeDomainKey("1"))
+ BridgeDomain.class, new BridgeDomainKey("bdn1"))
.child(L2Fib.class, new L2FibKey(new PhysAddress("FF:FF:FF:04:05:06"))));
// System.err.println(read);
assertEquals(read.size(), 0);
@@ -175,7 +206,7 @@ public class BdTest {
public void testReadL2FibAll() throws Exception {
// Deep child without a dedicated reader
final InstanceIdentifier<L2Fib> id = InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
- BridgeDomain.class, new BridgeDomainKey("1")).child(L2Fib.class);
+ BridgeDomain.class, new BridgeDomainKey("bdn1")).child(L2Fib.class);
final List<? extends DataObject> read = readerRegistry.read(id);
// System.err.println(read);
assertEquals(read.toString(), read.size(), 2);
@@ -204,19 +235,18 @@ public class BdTest {
final List<? extends DataObject> read =
readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child(
- BridgeDomain.class, new BridgeDomainKey("1")));
+ BridgeDomain.class, new BridgeDomainKey("bdn1")));
-// System.err.println(read);
assertEquals(read.size(), 1);
assertEquals(Iterables.find(readRoot.getBridgeDomains().getBridgeDomain(), new Predicate<BridgeDomain>() {
@Override
public boolean apply(final BridgeDomain input) {
-// System.err.println(input.getKey());
- return input.getKey().getName().equals("1");
+ return input.getKey().getName().equals("bdn1");
}
}), read.get(0));
}
+ @Ignore("Bridge domain customizer does not check whether the bd exists or not and fails with NPE, add it there")
@Test
public void testReadBridgeDomainNotExisting() throws Exception {
final List<? extends DataObject> read =
diff --git a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VppStateUtils.java b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/VppStateUtils.java
index 7a4a08eaf..e28e5b092 100644
--- a/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/vppstate/VppStateUtils.java
+++ b/v3po/impl/src/test/java/io/fd/honeycomb/v3po/impl/vppstate/VppStateUtils.java
@@ -20,10 +20,9 @@ import io.fd.honeycomb.v3po.impl.trans.ChildVppReader;
import io.fd.honeycomb.v3po.impl.trans.impl.CompositeChildVppReader;
import io.fd.honeycomb.v3po.impl.trans.impl.CompositeListVppReader;
import io.fd.honeycomb.v3po.impl.trans.impl.CompositeRootVppReader;
-import io.fd.honeycomb.v3po.impl.trans.impl.spi.RootVppReaderCustomizer;
import io.fd.honeycomb.v3po.impl.trans.util.ReflexiveChildReaderCustomizer;
import io.fd.honeycomb.v3po.impl.trans.util.ReflexiveRootReaderCustomizer;
-import io.fd.honeycomb.v3po.impl.trans.util.VppReaderUtils;
+import io.fd.honeycomb.v3po.impl.trans.util.VppRWUtils;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
@@ -38,32 +37,26 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.openvpp.vppjapi.vppApi;
-public final class VppStateUtils {
+final class VppStateUtils {
public VppStateUtils() {}
/**
* Create root VppState reader with all its children wired
*/
- public static CompositeRootVppReader<VppState, VppStateBuilder> getVppStateReader(@Nonnull final vppApi vppApi) {
- final RootVppReaderCustomizer<VppState, VppStateBuilder> rootVppReaderCustomizer =
- new ReflexiveRootReaderCustomizer<>(VppStateBuilder.class);
+ static CompositeRootVppReader<VppState, VppStateBuilder> getVppStateReader(@Nonnull final vppApi vppApi) {
final ChildVppReader<Version> versionReader = new CompositeChildVppReader<>(
- Version.class,
- new VersionCustomizer(vppApi));
+ Version.class, new VersionCustomizer(vppApi));
final CompositeListVppReader<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder>
- identifierBuilderCompositeListVppReader = new CompositeListVppReader<>(
+ bridgeDomainReader = new CompositeListVppReader<>(
BridgeDomain.class,
new BridgeDomainCustomizer(vppApi));
- final List<ChildVppReader<? extends ChildOf<BridgeDomains>>> bdChildReaders = new ArrayList<>();
- bdChildReaders.add(identifierBuilderCompositeListVppReader);
-
final ChildVppReader<BridgeDomains> bridgeDomainsReader = new CompositeChildVppReader<>(
BridgeDomains.class,
- bdChildReaders,
+ VppRWUtils.singletonChildReaderList(bridgeDomainReader),
new ReflexiveChildReaderCustomizer<>(BridgeDomainsBuilder.class));
final List<ChildVppReader<? extends ChildOf<VppState>>> childVppReaders = new ArrayList<>();
@@ -73,7 +66,7 @@ public final class VppStateUtils {
return new CompositeRootVppReader<>(
VppState.class,
childVppReaders,
- VppReaderUtils.<VppState>emptyAugReaderList(),
- rootVppReaderCustomizer);
+ VppRWUtils.<VppState>emptyAugReaderList(),
+ new ReflexiveRootReaderCustomizer<>(VppStateBuilder.class));
}
}