summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/ChildVppReader.java1
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/AbstractCompositeVppReader.java233
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeChildVppReader.java80
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeListVppReader.java127
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeRootVppReader.java71
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ChildVppReaderCustomizer.java29
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ListVppReaderCustomizer.java37
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/RootVppReaderCustomizer.java29
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/DelegatingReaderRegistry.java79
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/NoopReaderCustomizer.java29
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveChildReaderCustomizer.java56
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveRootReaderCustomizer.java41
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppApiReaderCustomizer.java33
-rw-r--r--v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppReaderUtils.java152
14 files changed, 997 insertions, 0 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 5d57c6064..8f2a1ce9e 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
@@ -13,6 +13,7 @@
* 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;
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
new file mode 100644
index 000000000..566c4fcc8
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/AbstractCompositeVppReader.java
@@ -0,0 +1,233 @@
+/*
+ * 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.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 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;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@Beta
+abstract class AbstractCompositeVppReader<D extends DataObject, B extends Builder<D>> implements VppReader<D> {
+
+ // TODO add debug + trace logs here and there
+
+ private final Map<Class<? extends DataObject>, ChildVppReader<? extends ChildOf<D>>> childReaders;
+ private final Map<Class<? extends DataObject>, ChildVppReader<? extends Augmentation<D>>> augReaders;
+ private final InstanceIdentifier<D> instanceIdentifier;
+
+ public 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.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;
+ }
+
+ 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
+ final D emptyValue = builder.build();
+
+ readCurrentAttributes(id, builder);
+
+ for (ChildVppReader<? extends ChildOf<D>> child : childReaders.values()) {
+ child.read(id, builder);
+ }
+
+ for (ChildVppReader<? extends Augmentation<D>> child : augReaders.values()) {
+ child.read(id, builder);
+ }
+
+ // Need to check whether anything was filled in to determine if data is present or not.
+ final D built = builder.build();
+ return built.equals(emptyValue) ? Collections.<D>emptyList() : Collections.singletonList(built);
+ }
+
+ @Nonnull
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
+ // This is read for one of children, we need to read and then filter, not parent)
+
+ // If this is target, just read
+ if (id.getTargetType().equals(getManagedDataObjectType().getTargetType())) {
+ return readCurrent((InstanceIdentifier<D>) id);
+ } else {
+ return readSubtree(id);
+ }
+ }
+
+ 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 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 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)));
+ }
+
+ protected abstract void readCurrentAttributes(final InstanceIdentifier<D> id, B builder);
+
+ protected abstract B getBuilder(InstanceIdentifier<? extends DataObject> 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 ?
+
+ List<DataObject> filtered = Lists.newArrayList();
+ for (DataObject parent : built) {
+ final InstanceIdentifier.PathArgument nextId =
+ VppReaderUtils.getNextId(absolutPath, InstanceIdentifier.create(parent.getClass()));
+
+ Optional<Method> method = VppReaderUtils.findMethodReflex(managedType, "get",
+ Collections.<Class<?>>emptyList(), nextId.getType());
+
+ if (method.isPresent()) {
+ filterSingle(filtered, parent, nextId, method);
+ } else {
+ // List child nodes
+ method = VppReaderUtils.findMethodReflex(managedType,
+ "get" + nextId.getType().getSimpleName(), Collections.<Class<?>>emptyList(), List.class);
+
+ if (method.isPresent()) {
+ filterList(filtered, parent, nextId, method);
+ } else {
+ throw new IllegalStateException(
+ "Unable to filter " + nextId + " from " + parent + " getters not found using reflexion");
+ }
+ }
+ }
+
+ return filtered;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void filterList(final List<DataObject> filtered, final DataObject parent,
+ final InstanceIdentifier.PathArgument nextId, final Optional<Method> method) {
+ final List<? extends DataObject> invoke = (List<? extends DataObject>)invoke(method.get(), nextId, parent);
+
+ if (nextId instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
+ final Identifier key = ((InstanceIdentifier.IdentifiableItem) nextId).getKey();
+ filtered.addAll(Collections2.filter(invoke, new Predicate<DataObject>() {
+ @Override
+ public boolean apply(@Nullable final DataObject input) {
+ final Optional<Method> keyGetter =
+ VppReaderUtils.findMethodReflex(nextId.getType(), "get",
+ Collections.<Class<?>>emptyList(), key.getClass());
+ final Object actualKey;
+ actualKey = invoke(keyGetter.get(), nextId, input);
+ return key.equals(actualKey);
+ }
+ }));
+ } else {
+ filtered.addAll(invoke);
+ }
+ }
+
+ private static void filterSingle(final List<DataObject> filtered, final DataObject parent,
+ final InstanceIdentifier.PathArgument nextId, final Optional<Method> method) {
+ filtered.add(nextId.getType().cast(invoke(method.get(), nextId, parent)));
+ }
+
+ private static Object invoke(final Method method,
+ final InstanceIdentifier.PathArgument nextId, final DataObject parent) {
+ try {
+ return method.invoke(parent);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ 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
new file mode 100644
index 000000000..7c66695c4
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeChildVppReader.java
@@ -0,0 +1,80 @@
+/*
+ * 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.impl;
+
+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 java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@Beta
+@ThreadSafe
+public class CompositeChildVppReader<C extends DataObject, B extends Builder<C>> extends AbstractCompositeVppReader<C, B>
+ implements ChildVppReader<C> {
+
+ private final ChildVppReaderCustomizer<C, B> customizer;
+
+ public CompositeChildVppReader(@Nonnull final Class<C> managedDataObjectType,
+ @Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
+ @Nonnull final List<ChildVppReader<? extends Augmentation<C>>> augReaders,
+ @Nonnull final ChildVppReaderCustomizer<C, B> customizer) {
+ super(managedDataObjectType, childReaders, augReaders);
+ this.customizer = customizer;
+ }
+
+ 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);
+ }
+
+ public CompositeChildVppReader(@Nonnull final Class<C> managedDataObjectType,
+ @Nonnull final ChildVppReaderCustomizer<C, B> customizer) {
+ this(managedDataObjectType, VppReaderUtils.<C>emptyChildReaderList(), VppReaderUtils.<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));
+
+ if(read.isPresent()) {
+ customizer.merge(parentBuilder, read.get());
+ }
+ }
+
+ @Override
+ protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) {
+ customizer.readCurrentAttributes(builder);
+ }
+
+ @Override
+ protected B getBuilder(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
+ return customizer.getBuilder();
+ }
+
+}
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
new file mode 100644
index 000000000..f280fdb76
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeListVppReader.java
@@ -0,0 +1,127 @@
+/*
+ * 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.impl;
+
+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 java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+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;
+
+@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;
+
+ public CompositeListVppReader(@Nonnull final Class<C> managedDataObjectType,
+ @Nonnull final List<ChildVppReader<? extends ChildOf<C>>> childReaders,
+ @Nonnull final List<ChildVppReader<? extends Augmentation<C>>> augReaders,
+ @Nonnull final ListVppReaderCustomizer<C, K, B> customizer) {
+ super(managedDataObjectType, childReaders, augReaders);
+ this.customizer = customizer;
+ }
+
+ 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);
+ }
+
+ public CompositeListVppReader(@Nonnull final Class<C> managedDataObjectType,
+ @Nonnull final ListVppReaderCustomizer<C, K, B> customizer) {
+ this(managedDataObjectType, VppReaderUtils.<C>emptyChildReaderList(), VppReaderUtils.<C>emptyAugReaderList(),
+ customizer);
+ }
+
+ @Override
+ protected List<C> readCurrent(@Nonnull final InstanceIdentifier<C> id) {
+ if(shouldReadAll(id)) {
+ return readList(id);
+ }
+ return 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();
+ }
+
+ 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>() {
+ @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));
+ }
+ });
+ }
+
+ private boolean shouldReadAll(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
+ final InstanceIdentifier instanceIdentifier = id.firstIdentifierOf(getManagedDataObjectType().getTargetType());
+ return instanceIdentifier == null || instanceIdentifier.isWildcarded();
+ }
+
+ @Override
+ protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) {
+ customizer.readCurrentAttributes(id, builder);
+ }
+
+ @Override
+ protected B getBuilder(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
+ return customizer.getBuilder(id.firstKeyOf(getManagedDataObjectType().getTargetType()));
+ }
+
+}
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
new file mode 100644
index 000000000..605f1b628
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/CompositeRootVppReader.java
@@ -0,0 +1,71 @@
+/*
+ * 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.impl;
+
+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 java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@Beta
+@ThreadSafe
+public final class CompositeRootVppReader<C extends DataObject, B extends Builder<C>> extends AbstractCompositeVppReader<C, B>
+ implements VppReader<C> {
+
+ private final RootVppReaderCustomizer<C, B> customizer;
+
+ 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 RootVppReaderCustomizer<C, B> customizer) {
+ super(managedDataObjectType, childReaders, childAugReaders);
+ this.customizer = customizer;
+ }
+
+ 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);
+ }
+
+ public CompositeRootVppReader(@Nonnull final Class<C> managedDataObjectType,
+ @Nonnull final RootVppReaderCustomizer<C, B> customizer) {
+ this(managedDataObjectType, VppReaderUtils.<C>emptyChildReaderList(), VppReaderUtils.<C>emptyAugReaderList(),
+ customizer);
+ }
+
+ @Override
+ protected void readCurrentAttributes(@Nonnull final InstanceIdentifier<C> id, @Nonnull final B builder) {
+ customizer.readCurrentAttributes(builder);
+ }
+
+ @Override
+ protected B getBuilder(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
+ // TODO instantiate builder from customizer(as is) or reflection ?
+ return customizer.getBuilder();
+ }
+
+}
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
new file mode 100644
index 000000000..7cf0b60f6
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ChildVppReaderCustomizer.java
@@ -0,0 +1,29 @@
+/*
+ * 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.impl.spi;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+@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);
+}
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
new file mode 100644
index 000000000..855e8488d
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/ListVppReaderCustomizer.java
@@ -0,0 +1,37 @@
+/*
+ * 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.impl.spi;
+
+import com.google.common.annotations.Beta;
+import java.util.List;
+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;
+
+@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);
+
+ List<InstanceIdentifier<C>> getAllIds(InstanceIdentifier<C> id);
+
+ void merge(Builder<?> builder, List<C> currentBuilder);
+}
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
new file mode 100644
index 000000000..fe09220d2
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/impl/spi/RootVppReaderCustomizer.java
@@ -0,0 +1,29 @@
+/*
+ * 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.impl.spi;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+@Beta
+public interface RootVppReaderCustomizer<C extends DataObject, B extends Builder<C>> {
+
+ B getBuilder();
+
+ void readCurrentAttributes(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
new file mode 100644
index 000000000..0aeda896a
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/DelegatingReaderRegistry.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.Function;
+import com.google.common.base.Preconditions;
+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.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class DelegatingReaderRegistry implements ReaderRegistry {
+
+ private final Map<Class<? extends DataObject>, VppReader<? extends DataObject>> rootReaders;
+
+ 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();
+ }
+ });
+ }
+
+ @Override
+ @Nonnull
+ public List<? extends DataObject> readAll() {
+ final List<DataObject> objects = Lists.newArrayListWithExpectedSize(rootReaders.size());
+ for (VppReader<? extends DataObject> rootReader : rootReaders.values()) {
+ final List<? extends DataObject> read = rootReader.read(rootReader.getManagedDataObjectType());
+ objects.addAll(read);
+ }
+ return objects;
+ }
+
+ @Nonnull
+ @Override
+ public List<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id) {
+ final InstanceIdentifier.PathArgument first = Preconditions.checkNotNull(
+ Iterables.getFirst(id.getPathArguments(), null), "Empty id");
+ final VppReader<? extends DataObject> vppReader = rootReaders.get(first.getType());
+ Preconditions.checkNotNull(vppReader,
+ "Unable to read %s. Missing reader. Current readers for: %s", id, rootReaders.keySet());
+ return vppReader.read(id);
+ }
+
+ @Nonnull
+ @Override
+ public InstanceIdentifier<DataObject> getManagedDataObjectType() {
+ throw new UnsupportedOperationException("Root registry has no type");
+ }
+
+}
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
new file mode 100644
index 000000000..050f7171f
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/NoopReaderCustomizer.java
@@ -0,0 +1,29 @@
+/*
+ * 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 io.fd.honeycomb.v3po.impl.trans.impl.spi.RootVppReaderCustomizer;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public abstract class NoopReaderCustomizer<C extends DataObject, B extends Builder<C>> implements RootVppReaderCustomizer<C, B> {
+
+ @Override
+ public void readCurrentAttributes(final B builder) {
+ // Noop
+ }
+}
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
new file mode 100644
index 000000000..28a44eb07
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveChildReaderCustomizer.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import io.fd.honeycomb.v3po.impl.trans.impl.spi.ChildVppReaderCustomizer;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Might be slow !
+ */
+public class ReflexiveChildReaderCustomizer<C extends DataObject, B extends Builder<C>>
+ extends ReflexiveRootReaderCustomizer<C, B>
+ implements ChildVppReaderCustomizer<C,B> {
+
+ public ReflexiveChildReaderCustomizer(final Class<B> builderClass) {
+ super(builderClass);
+ }
+
+ // TODO Could be just a default implementation in interface (making this a mixin)
+
+ @Override
+ public void merge(final Builder<? extends DataObject> parentBuilder, final C readValue) {
+ final Optional<Method> method =
+ VppReaderUtils.findMethodReflex(parentBuilder.getClass(), "set",
+ Collections.<Class<?>>singletonList(readValue.getClass()), parentBuilder.getClass());
+
+ Preconditions.checkArgument(method.isPresent(), "Unable to set %s to %s", readValue, parentBuilder);
+
+ try {
+ method.get().invoke(parentBuilder, readValue);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new IllegalArgumentException("Unable to set " + readValue + " to " + parentBuilder, e);
+ }
+ }
+
+}
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
new file mode 100644
index 000000000..2a98bbe5b
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/ReflexiveRootReaderCustomizer.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Might be slow !
+ */
+public class ReflexiveRootReaderCustomizer<C extends DataObject, B extends Builder<C>> extends NoopReaderCustomizer<C, B> {
+
+ private final Class<B> builderClass;
+
+ public ReflexiveRootReaderCustomizer(final Class<B> builderClass) {
+ this.builderClass = builderClass;
+ }
+
+ @Override
+ public B getBuilder() {
+ try {
+ return builderClass.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new IllegalStateException("Unable to instantiate " + builderClass, 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
new file mode 100644
index 000000000..584c7823f
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppApiReaderCustomizer.java
@@ -0,0 +1,33 @@
+/*
+ * 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.annotations.Beta;
+
+@Beta
+public abstract class VppApiReaderCustomizer {
+
+ private final org.openvpp.vppjapi.vppApi vppApi;
+
+ public VppApiReaderCustomizer(final org.openvpp.vppjapi.vppApi vppApi) {
+ this.vppApi = vppApi;
+ }
+
+ 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/VppReaderUtils.java
new file mode 100644
index 000000000..07c54ae90
--- /dev/null
+++ b/v3po/impl/src/main/java/io/fd/honeycomb/v3po/impl/trans/util/VppReaderUtils.java
@@ -0,0 +1,152 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import io.fd.honeycomb.v3po.impl.trans.ChildVppReader;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+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;
+
+public final class VppReaderUtils {
+
+ private VppReaderUtils() {}
+
+ /**
+ * Find next item in ID after provided type
+ */
+ @Nonnull
+ public static InstanceIdentifier.PathArgument getNextId(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+ @Nonnull final InstanceIdentifier<? extends DataObject> type) {
+ // TODO this is inefficient(maybe, depending on actual Iterable type)
+ final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
+ final int i = Iterables.indexOf(pathArguments, new Predicate<InstanceIdentifier.PathArgument>() {
+ @Override
+ public boolean apply(final InstanceIdentifier.PathArgument input) {
+ return input.getType().isAssignableFrom(type.getTargetType());
+ }
+ });
+ Preconditions.checkArgument(i >= 0, "Unable to find %s type in %s", type.getTargetType(), id);
+ return Iterables.get(pathArguments, i + 1);
+ }
+
+ public static <T> List<ChildVppReader<? extends ChildOf<T>>> emptyChildReaderList() {
+ return Collections.emptyList();
+ }
+
+ public static <T> List<ChildVppReader<? extends Augmentation<T>>> emptyAugReaderList() {
+ return Collections.emptyList();
+ }
+
+ public static <T> List<ChildVppReader<? extends Augmentation<T>>> singletonAugReaderList(
+ ChildVppReader<? extends Augmentation<T>> item) {
+ return Collections.<ChildVppReader<? extends Augmentation<T>>>singletonList(item);
+ }
+
+ public static <T> List<ChildVppReader<? extends ChildOf<T>>> singletonChildReaderList(
+ ChildVppReader<? extends ChildOf<T>> item) {
+ return Collections.<ChildVppReader<? extends ChildOf<T>>>singletonList(item);
+ }
+
+ /**
+ * Replace last item in ID with a provided IdentifiableItem of the same type
+ */
+ @SuppressWarnings("unchecked")
+ @Nonnull
+ public static <D extends DataObject & Identifiable<K>, K extends Identifier<D>> InstanceIdentifier<D> getCurrentId(
+ @Nonnull final InstanceIdentifier<D> id, final InstanceIdentifier.IdentifiableItem<D, K> currentBdItem) {
+
+ final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
+ final Iterable<InstanceIdentifier.PathArgument> withoutCurrent =
+ Iterables.limit(pathArguments, Iterables.size(pathArguments) - 1);
+ final Iterable<InstanceIdentifier.PathArgument> concat =
+ Iterables.concat(withoutCurrent, Collections.singleton(currentBdItem));
+ return (InstanceIdentifier<D>) InstanceIdentifier.create(concat);
+ }
+
+ /**
+ * Create IdentifiableItem from target type of provided ID with provided key
+ */
+ @Nonnull
+ public static <D extends DataObject & Identifiable<K>, K extends Identifier<D>> InstanceIdentifier.IdentifiableItem<D, K> getCurrentIdItem(
+ @Nonnull final InstanceIdentifier<D> id, final K key) {
+ return new InstanceIdentifier.IdentifiableItem<>(id.getTargetType(), key);
+ }
+
+ /**
+ * Trim InstanceIdentifier at indexOf(type)
+ */
+ @SuppressWarnings("unchecked")
+ @Nonnull
+ public static <D extends DataObject> InstanceIdentifier<D> cutId(@Nonnull final InstanceIdentifier<? extends DataObject> id,
+ @Nonnull final InstanceIdentifier<D> type) {
+ final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments();
+ final int i = Iterables.indexOf(pathArguments, new Predicate<InstanceIdentifier.PathArgument>() {
+ @Override
+ public boolean apply(final InstanceIdentifier.PathArgument input) {
+ return input.getType().equals(type.getTargetType());
+ }
+ });
+ Preconditions.checkArgument(i >= 0, "ID %s does not contain %s", id, type);
+ return (InstanceIdentifier<D>) InstanceIdentifier.create(Iterables.limit(pathArguments, i + 1));
+ }
+
+ /**
+ * Find a specific method using reflection
+ */
+ @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;
+ }
+
+ for (int i = 0; i < parameterTypes.length; i++) {
+ if (!parameterTypes[i].isAssignableFrom(paramTypes.get(i))) {
+ continue top;
+ }
+ }
+
+ if (!method.getReturnType().equals(retType)) {
+ continue;
+ }
+
+ return Optional.of(method);
+ }
+
+ return Optional.absent();
+ }
+}