diff options
author | Maros Marsalek <mmarsale@cisco.com> | 2016-07-14 10:41:49 +0200 |
---|---|---|
committer | Maros Marsalek <mmarsale@cisco.com> | 2016-07-25 10:34:16 +0200 |
commit | f15aed916c69b0766c7bed2dc7fe534f48b97ac9 (patch) | |
tree | 529281c96caf3c5325c17ec89cb3e4a154121091 /v3po/translate-utils/src/main/java | |
parent | 4e6b846c342b2c9e9443e3d3472685e5acb32fa3 (diff) |
HONEYCOMB-122: Reader registry integration tests
Add IT test for read infrastructure + some additional unit tests
+ Make Read/Write Factory autoCloseable
Change-Id: I6eab8e6df2c2132af01cea0a9c4b9bece7dc9b74
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'v3po/translate-utils/src/main/java')
8 files changed, 110 insertions, 6 deletions
diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java index ba9d8e16f..2a565d9f2 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java @@ -117,7 +117,7 @@ public final class RWUtils { } /** - * Create a map from a collection, checking for duplicity in the process + * Create an ordered map from a collection, checking for duplicity in the process. */ @Nonnull public static <K, V> Map<K, V> uniqueLinkedIndex(@Nonnull final Collection<V> values, @Nonnull final Function<? super V, K> keyFunction) { @@ -152,6 +152,9 @@ public final class RWUtils { /** * Transform a keyed instance identifier into a wildcarded one. + * <p/> + * ! This has to be called also for wildcarded List instance identifiers + * due to weird behavior of equals in InstanceIdentifier ! */ @SuppressWarnings("unchecked") public static <D extends DataObject> InstanceIdentifier<D> makeIidWildcarded(final InstanceIdentifier<D> id) { @@ -162,6 +165,19 @@ public final class RWUtils { return (InstanceIdentifier<D>) InstanceIdentifier.create(transformedPathArguments); } + /** + * Transform a keyed instance identifier into a wildcarded one, keeping keys except the last item. + */ + @SuppressWarnings("unchecked") + public static <D extends DataObject> InstanceIdentifier<D> makeIidLastWildcarded(final InstanceIdentifier<D> id) { + final InstanceIdentifier.Item<D> wildcardedItem = new InstanceIdentifier.Item<>(id.getTargetType()); + final Iterable<InstanceIdentifier.PathArgument> pathArguments = id.getPathArguments(); + return (InstanceIdentifier<D>) InstanceIdentifier.create( + Iterables.concat( + Iterables.limit(pathArguments, Iterables.size(pathArguments) - 1), + Collections.singleton(wildcardedItem))); + } + private static InstanceIdentifier.PathArgument cleanPathArgumentFromKeys(final InstanceIdentifier.PathArgument pathArgument) { return pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?> ? new InstanceIdentifier.Item<>(pathArgument.getType()) diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/ReflectionUtils.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/ReflectionUtils.java index ea0b3b2c4..728c4f80d 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/ReflectionUtils.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/ReflectionUtils.java @@ -44,7 +44,7 @@ public final class ReflectionUtils { @Nonnull final List<Class<?>> paramTypes, @Nonnull final Class<?> retType) { for (Method method : managedType.getMethods()) { - if(isMethodMatch(prefix, paramTypes, retType, method)) { + if (isMethodMatch(prefix, paramTypes, retType, method)) { return Optional.of(method); } } diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveListReaderCustomizer.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveListReaderCustomizer.java new file mode 100644 index 000000000..8ad323cc3 --- /dev/null +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveListReaderCustomizer.java @@ -0,0 +1,65 @@ +/* + * 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.translate.util.read; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.spi.read.ListReaderCustomizer; +import io.fd.honeycomb.v3po.translate.util.ReflectionUtils; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collections; +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; + +/** + * Might be slow ! + */ +public abstract class ReflexiveListReaderCustomizer<C extends DataObject & Identifiable<K>, K extends Identifier<C>, B extends Builder<C>> + extends ReflexiveReaderCustomizer<C, B> + implements ListReaderCustomizer<C, K, B> { + + + public ReflexiveListReaderCustomizer(final Class<C> typeClass, final Class<B> builderClass) { + super(typeClass, builderClass); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final C readValue) { + merge(parentBuilder, Collections.singletonList(readValue)); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final List<C> readData) { + final Optional<Method> method = + ReflectionUtils.findMethodReflex(parentBuilder.getClass(), "set" + getTypeClass().getSimpleName(), + Collections.singletonList(List.class), parentBuilder.getClass()); + + checkArgument(method.isPresent(), "Unable to set %s to %s", readData, parentBuilder); + + try { + method.get().invoke(parentBuilder, readData); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalArgumentException("Unable to set " + readData + " to " + parentBuilder, e); + } + } +} diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReader.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReader.java index 51725e728..2b2d9300b 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReader.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReader.java @@ -28,7 +28,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; * <p/> * Might be slow due to reflection ! */ -public final class ReflexiveReader<C extends DataObject, B extends Builder<C>> extends AbstractGenericReader<C, B> { +public class ReflexiveReader<C extends DataObject, B extends Builder<C>> extends AbstractGenericReader<C, B> { private final ReflexiveReaderCustomizer<C, B> customizer; diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReaderCustomizer.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReaderCustomizer.java index f9efca3dc..a6b9bf08e 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReaderCustomizer.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/ReflexiveReaderCustomizer.java @@ -33,7 +33,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; /** * Might be slow ! */ -final class ReflexiveReaderCustomizer<C extends DataObject, B extends Builder<C>> extends NoopReaderCustomizer<C, B> { +class ReflexiveReaderCustomizer<C extends DataObject, B extends Builder<C>> extends NoopReaderCustomizer<C, B> { private final Class<C> typeClass; private final Class<B> builderClass; diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReader.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReader.java index 64ecaf095..aa9b2dc92 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReader.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReader.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.translate.util.read.registry; import static com.google.common.base.Preconditions.checkArgument; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; @@ -53,6 +54,11 @@ class CompositeReader<D extends DataObject, B extends Builder<D>> extends Abstra this.childReaders = childReaders; } + @VisibleForTesting + ImmutableMap<Class<?>, Reader<? extends DataObject, ? extends Builder<?>>> getChildReaders() { + return childReaders; + } + @SuppressWarnings("unchecked") public static <D extends DataObject> InstanceIdentifier<D> appendTypeToId( final InstanceIdentifier<? extends DataObject> parentId, final InstanceIdentifier<D> type) { @@ -66,11 +72,14 @@ class CompositeReader<D extends DataObject, B extends Builder<D>> extends Abstra public Optional<? extends DataObject> read(@Nonnull final InstanceIdentifier<? extends DataObject> id, @Nonnull final ReadContext ctx) throws ReadFailedException { if (shouldReadCurrent(id)) { + LOG.trace("{}: Reading current: {}", this, id); return readCurrent((InstanceIdentifier<D>) id, ctx); } else if (shouldDelegateToChild(id)) { + LOG.trace("{}: Reading child: {}", this, id); return readSubtree(id, ctx); } else { // Fallback + LOG.trace("{}: Delegating read: {}", this, id); return delegate.read(id, ctx); } } @@ -95,10 +104,11 @@ class CompositeReader<D extends DataObject, B extends Builder<D>> extends Abstra @SuppressWarnings("unchecked") private void readChildren(final InstanceIdentifier<D> id, @Nonnull final ReadContext ctx, final B builder) throws ReadFailedException { + LOG.debug("{}: Reading children: {}", this, childReaders.keySet()); for (Reader child : childReaders.values()) { - LOG.debug("{}: Reading child node from: {}", this, child); final InstanceIdentifier childId = appendTypeToId(id, child.getManagedDataObjectType()); + LOG.debug("{}: Reading child from: {}", this, child); if (child instanceof ListReader) { final List<? extends DataObject> list = ((ListReader) child).readList(childId, ctx); ((ListReader) child).merge(builder, list); diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistry.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistry.java index 0a948c7a8..a9f606ae2 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistry.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistry.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.translate.util.read.registry; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedListMultimap; @@ -31,6 +32,7 @@ import io.fd.honeycomb.v3po.translate.util.RWUtils; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; @@ -59,6 +61,11 @@ public final class CompositeReaderRegistry implements ReaderRegistry { this.rootReaders = RWUtils.uniqueLinkedIndex(checkNotNull(rootReaders), RWUtils.MANAGER_CLASS_FUNCTION); } + @VisibleForTesting + Map<Class<? extends DataObject>, Reader<? extends DataObject, ? extends Builder<?>>> getRootReaders() { + return rootReaders; + } + @Override @Nonnull public Multimap<InstanceIdentifier<? extends DataObject>, ? extends DataObject> readAll( @@ -101,4 +108,10 @@ public final class CompositeReaderRegistry implements ReaderRegistry { LOG.debug("Reading from delegate: {}", reader); return reader.read(id, ctx); } + + @Override + public String toString() { + return getClass().getSimpleName() + + rootReaders.keySet().stream().map(Class::getSimpleName).collect(Collectors.toList()); + } } diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReader.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReader.java index 98fcac673..50a20656e 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReader.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReader.java @@ -89,7 +89,7 @@ class SubtreeReader<D extends DataObject, B extends Builder<D>> implements Reade LOG.debug("{}: Subtree node managed by this writer requested: {}. Reading current and filtering", this, id); // If there's no dedicated reader, use read current final InstanceIdentifier<D> currentId = RWUtils.cutId(id, getManagedDataObjectType()); - final Optional<? extends DataObject> current = read(currentId, ctx); + final Optional<? extends DataObject> current = delegate.read(currentId, ctx); // then perform post-reading filtering (return only requested sub-node) final Optional<? extends DataObject> readSubtree = current.isPresent() ? filterSubtree(current.get(), id, getManagedDataObjectType().getTargetType()) |