From 9779f4b3ffe24bb2338630c66169da92c880ffbb Mon Sep 17 00:00:00 2001 From: Jan Srnicek Date: Fri, 3 Nov 2017 13:33:53 +0100 Subject: HONEYCOMB-359 - Wildcarded writers Adds option to specify subtree writer that can handle whole subtree of nodes without having whole subtree specified. Its checking if node is children at runtime, rather than having pre-computed tree Change-Id: Ic46f2bd6de84f0dd14865825399f5a90a1f80859 Signed-off-by: Jan Srnicek --- infra/translate-impl/pom.xml | 12 +++ .../registry/CompositeReaderRegistryBuilder.java | 22 ++-- .../impl/write/registry/FlatWriterRegistry.java | 67 ++++++------ .../write/registry/FlatWriterRegistryBuilder.java | 14 ++- .../impl/write/registry/SubtreeWriter.java | 31 +++++- .../write/registry/FlatWriterRegistryTest.java | 72 +++++++++++-- .../registry/WildcardedSubtreeWriterTest.java | 115 +++++++++++++++++++++ 7 files changed, 279 insertions(+), 54 deletions(-) create mode 100644 infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/WildcardedSubtreeWriterTest.java (limited to 'infra/translate-impl') diff --git a/infra/translate-impl/pom.xml b/infra/translate-impl/pom.xml index c11893a1b..aa2a48b19 100644 --- a/infra/translate-impl/pom.xml +++ b/infra/translate-impl/pom.xml @@ -53,6 +53,12 @@ test-jar test + + io.fd.honeycomb.it + honeycomb-test-model + ${project.version} + test + junit @@ -69,6 +75,12 @@ hamcrest-all test + + org.slf4j + slf4j-simple + 1.7.25 + test + diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/registry/CompositeReaderRegistryBuilder.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/registry/CompositeReaderRegistryBuilder.java index f8290f166..4f7e1e140 100644 --- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/registry/CompositeReaderRegistryBuilder.java +++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/registry/CompositeReaderRegistryBuilder.java @@ -16,8 +16,6 @@ package io.fd.honeycomb.translate.impl.read.registry; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.common.collect.ImmutableMap; import io.fd.honeycomb.translate.impl.read.GenericListReader; import io.fd.honeycomb.translate.impl.read.GenericReader; @@ -29,12 +27,6 @@ import io.fd.honeycomb.translate.read.registry.ReaderRegistry; import io.fd.honeycomb.translate.read.registry.ReaderRegistryBuilder; import io.fd.honeycomb.translate.util.AbstractSubtreeManagerRegistryBuilderBuilder; import io.fd.honeycomb.translate.util.YangDAG; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.concurrent.NotThreadSafe; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Identifiable; @@ -43,6 +35,15 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; +import javax.annotation.concurrent.NotThreadSafe; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; + @NotThreadSafe public final class CompositeReaderRegistryBuilder extends AbstractSubtreeManagerRegistryBuilderBuilder>, ReaderRegistry> @@ -62,6 +63,11 @@ public final class CompositeReaderRegistryBuilder : SubtreeReader.createForReader(handledChildren, reader); } + @Override + protected Reader> getWildcardedSubtreeHandler(@Nonnull Reader> handler) { + throw new UnsupportedOperationException("Wildcarded readers are not supported"); + } + @Override public void addStructuralReader(@Nonnull InstanceIdentifier id, @Nonnull Class> builderType) { diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java index 146ddb9c5..c3bc1ee0e 100644 --- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java +++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistry.java @@ -21,7 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; @@ -32,12 +31,15 @@ import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.Writer; import io.fd.honeycomb.translate.write.registry.UpdateFailedException; import io.fd.honeycomb.translate.write.registry.WriterRegistry; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; @@ -54,39 +56,23 @@ final class FlatWriterRegistry implements WriterRegistry { private static final Logger LOG = LoggerFactory.getLogger(FlatWriterRegistry.class); - // All types handled by writers directly or as children - private final ImmutableSet> handledTypes; - private final Set> writersOrderReversed; private final Set> writersOrder; - private final Map, Writer> writers; + private final Map, Writer> writersById; + private final Set> writers; /** * Create flat registry instance. * - * @param writers immutable, ordered map of writers to use to process updates. Order of the writers has to be one in + * @param writersById immutable, ordered map of writers to use to process updates. Order of the writers has to be one in * which create and update operations should be handled. Deletes will be handled in reversed order. * All deletes are handled before handling all the updates. */ - FlatWriterRegistry(@Nonnull final ImmutableMap, Writer> writers) { - this.writers = writers; - this.writersOrderReversed = Sets.newLinkedHashSet(Lists.reverse(Lists.newArrayList(writers.keySet()))); - this.writersOrder = writers.keySet(); - this.handledTypes = getAllHandledTypes(writers); - } - - private static ImmutableSet> getAllHandledTypes( - @Nonnull final ImmutableMap, Writer> writers) { - final ImmutableSet.Builder> handledTypesBuilder = ImmutableSet.builder(); - for (Map.Entry, Writer> writerEntry : writers.entrySet()) { - final InstanceIdentifier writerType = writerEntry.getKey(); - final Writer writer = writerEntry.getValue(); - handledTypesBuilder.add(writerType); - if (writer instanceof SubtreeWriter) { - handledTypesBuilder.addAll(((SubtreeWriter) writer).getHandledChildTypes()); - } - } - return handledTypesBuilder.build(); + FlatWriterRegistry(@Nonnull final ImmutableMap, Writer> writersById) { + this.writersById = writersById; + this.writersOrderReversed = Sets.newLinkedHashSet(Lists.reverse(Lists.newArrayList(writersById.keySet()))); + this.writersOrder = writersById.keySet(); + this.writers = writersById.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toSet()); } @Override @@ -145,9 +131,9 @@ final class FlatWriterRegistry implements WriterRegistry { if (writer == null) { // This node must be handled by a subtree writer, find it and call it or else fail - checkArgument(handledTypes.contains(singleType), "Unable to process update. Missing writers for: %s", - singleType); writer = getSubtreeWriterResponsible(singleType); + checkArgument(writer != null, "Unable to process update. Missing writers for: %s", + singleType); singleTypeUpdates = getParentDataObjectUpdate(ctx, updates, writer); } @@ -168,9 +154,9 @@ final class FlatWriterRegistry implements WriterRegistry { @Nullable private Writer getSubtreeWriterResponsible(final InstanceIdentifier singleType) { - return writers.values().stream() + return writersById.values().stream() .filter(w -> w instanceof SubtreeWriter) - .filter(w -> ((SubtreeWriter) w).getHandledChildTypes().contains(singleType)) + .filter(w -> w.canProcess(singleType)) .findFirst() .orElse(null); } @@ -249,10 +235,23 @@ final class FlatWriterRegistry implements WriterRegistry { private void checkAllTypesCanBeHandled( @Nonnull final Multimap, ? extends DataObjectUpdate> updates) { - if (!handledTypes.containsAll(updates.keySet())) { - final Sets.SetView> missingWriters = Sets.difference(updates.keySet(), handledTypes); - LOG.warn("Unable to process update. Missing writers for: {}", missingWriters); - throw new IllegalArgumentException("Unable to process update. Missing writers for: " + missingWriters); + + List> noWriterNodes = new ArrayList<>(); + for (InstanceIdentifier id : updates.keySet()) { + // either there is direct writer for the iid + if (writersById.containsKey(id)) { + continue; + } else { + // or subtree one + if (writers.stream().anyMatch(o -> o.canProcess(id))) { + continue; + } + } + noWriterNodes.add(id); + } + + if (!noWriterNodes.isEmpty()) { + throw new IllegalArgumentException("Unable to process update. Missing writers for: " + noWriterNodes); } } @@ -269,7 +268,7 @@ final class FlatWriterRegistry implements WriterRegistry { @Nullable private Writer getWriter(@Nonnull final InstanceIdentifier singleType) { - return writers.get(singleType); + return writersById.get(singleType); } } diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilder.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilder.java index 0c6d0a1b4..43606064e 100644 --- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilder.java +++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryBuilder.java @@ -24,15 +24,16 @@ import io.fd.honeycomb.translate.write.Writer; import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; import io.fd.honeycomb.translate.write.registry.WriterRegistry; import io.fd.honeycomb.translate.write.registry.WriterRegistryBuilder; -import java.util.Set; -import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.concurrent.NotThreadSafe; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; +import javax.annotation.concurrent.NotThreadSafe; +import java.util.Set; +import java.util.stream.Collectors; + /** * Builder for {@link FlatWriterRegistry} allowing users to specify inter-writer relationships. */ @@ -53,6 +54,11 @@ public final class FlatWriterRegistryBuilder return SubtreeWriter.createForWriter(handledChildren, writer); } + @Override + protected Writer getWildcardedSubtreeHandler(@Nonnull Writer handler) { + return SubtreeWriter.createWildcardedForWriter(handler); + } + /** * Create FlatWriterRegistry with writers ordered according to submitted relationships. */ diff --git a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java index b2a571b40..a1a5f3fd0 100644 --- a/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java +++ b/infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/write/registry/SubtreeWriter.java @@ -37,15 +37,16 @@ final class SubtreeWriter implements Writer { private final Writer delegate; private final Set> handledChildTypes = new HashSet<>(); + private boolean isWildcarded = false; - private SubtreeWriter(final Writer delegate, Set> handledTypes) { + private SubtreeWriter(final Writer delegate, final Set> handledTypes) { this.delegate = delegate; for (InstanceIdentifier handledType : handledTypes) { // Iid has to start with writer's handled root type checkArgument(delegate.getManagedDataObjectType().getTargetType().equals( handledType.getPathArguments().iterator().next().getType()), "Handled node from subtree has to be identified by an instance identifier starting from: %s." - + "Instance identifier was: %s", getManagedDataObjectType().getTargetType(), handledType); + + "Instance identifier was: %s", getManagedDataObjectType().getTargetType(), handledType); checkArgument(Iterables.size(handledType.getPathArguments()) > 1, "Handled node from subtree identifier too short: %s", handledType); handledChildTypes.add(InstanceIdentifier.create(Iterables.concat( @@ -53,6 +54,11 @@ final class SubtreeWriter implements Writer { } } + private SubtreeWriter(final Writer delegate) { + this.delegate = delegate; + this.isWildcarded = true; + } + /** * Return set of types also handled by this writer. All of the types are children of the type managed by this * writer excluding the type of this writer. @@ -74,6 +80,20 @@ final class SubtreeWriter implements Writer { return delegate.supportsDirectUpdate(); } + @Override + public boolean canProcess(@Nonnull InstanceIdentifier instanceIdentifier) { + if (isWildcarded) { + final Class parent = delegate.getManagedDataObjectType().getTargetType(); + for (InstanceIdentifier.PathArgument pathArgument : instanceIdentifier.getPathArguments()) { + if (pathArgument.getType().equals(parent)) { + return true; + } + } + return false; + } + return handledChildTypes.contains(instanceIdentifier); + } + @Override @Nonnull public InstanceIdentifier getManagedDataObjectType() { @@ -87,4 +107,11 @@ final class SubtreeWriter implements Writer { @Nonnull final Writer writer) { return new SubtreeWriter<>(writer, handledChildren); } + + /** + * Wrap a writer as a subtree writer. + */ + static Writer createWildcardedForWriter(@Nonnull final Writer writer) { + return new SubtreeWriter<>(writer); + } } diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java index 151436975..01852d13f 100644 --- a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java +++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/FlatWriterRegistryTest.java @@ -25,6 +25,7 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; @@ -39,15 +40,19 @@ import io.fd.honeycomb.translate.util.DataObjects.DataObject1; import io.fd.honeycomb.translate.util.DataObjects.DataObject2; import io.fd.honeycomb.translate.write.DataObjectUpdate; import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; import io.fd.honeycomb.translate.write.Writer; import io.fd.honeycomb.translate.write.registry.UpdateFailedException; import io.fd.honeycomb.translate.write.registry.WriterRegistry; import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.stubbing.Answer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -72,6 +77,18 @@ public class FlatWriterRegistryTest { when(writer1.getManagedDataObjectType()).thenReturn(DataObject1.IID); when(writer2.getManagedDataObjectType()).thenReturn(DataObject2.IID); when(writer3.getManagedDataObjectType()).thenReturn(DataObjects.DataObject3.IID); + when(writer4.getManagedDataObjectType()).thenReturn(DataObjects.DataObject1ChildK.IID); + // TODO - HONEYCOMB-412 - thenCallRealMethod doest work with default methods + // https://stackoverflow.com/questions/27663252/can-you-make-mockito-1-10-17-work-with-default-methods-in-interfaces + when(writer1.canProcess(any())).thenAnswer(answerWithImpl()); + when(writer2.canProcess(any())).thenAnswer(answerWithImpl()); + when(writer3.canProcess(any())).thenAnswer(answerWithImpl()); + when(writer4.canProcess(any())).thenAnswer(answerWithImpl()); + } + + private static Answer answerWithImpl() { + return invocationOnMock -> new CheckedMockWriter(Writer.class.cast(invocationOnMock.getMock())).canProcess( + InstanceIdentifier.class.cast(invocationOnMock.getArguments()[0])); } @Test @@ -112,8 +129,12 @@ public class FlatWriterRegistryTest { inOrder.verify(writer1).processModification(iid, dataObject, dataObject, ctx); inOrder.verify(writer2).processModification(iid2, dataObject2, dataObject2, ctx); - verifyNoMoreInteractions(writer1); - verifyNoMoreInteractions(writer2); + // TODO - HONEYCOMB-412 -reintroduce verifyNoMoreInteractions and remove manual verify + // we are really interested just in invocations of processModification(),so adding specific verify to check that + verify(writer1,times(1)).processModification(any(),any(),any(),any()); + verify(writer2,times(1)).processModification(any(),any(),any(),any()); + //verifyNoMoreInteractions(writer1); + //verifyNoMoreInteractions(writer2); } @Test @@ -136,8 +157,12 @@ public class FlatWriterRegistryTest { inOrder.verify(writer2).processModification(iid2, dataObject2, null, ctx); inOrder.verify(writer1).processModification(iid, dataObject, null, ctx); - verifyNoMoreInteractions(writer1); - verifyNoMoreInteractions(writer2); + // TODO - HONEYCOMB-412 -reintroduce verifyNoMoreInteractions and remove manual verify + // we are really interested just in invocations of processModification(),so adding specific verify to check that + verify(writer1,times(1)).processModification(any(),any(),any(),any()); + verify(writer2,times(1)).processModification(any(),any(),any(),any()); + //verifyNoMoreInteractions(writer1); + //verifyNoMoreInteractions(writer2); } @Test @@ -170,8 +195,12 @@ public class FlatWriterRegistryTest { inOrder.verify(writer1).processModification(iid, dataObject, dataObject, ctx); inOrder.verify(writer2).processModification(iid2, dataObject2, dataObject2, ctx); - verifyNoMoreInteractions(writer1); - verifyNoMoreInteractions(writer2); + // TODO - HONEYCOMB-412 -reintroduce verifyNoMoreInteractions and remove manual verify + // we are really interested just in invocations of processModification(),so adding specific verify to check that + verify(writer1,times(2)).processModification(any(),any(),any(),any()); + verify(writer2,times(2)).processModification(any(),any(),any(),any()); + //verifyNoMoreInteractions(writer1); + //verifyNoMoreInteractions(writer2); } @Test(expected = IllegalArgumentException.class) @@ -298,4 +327,35 @@ public class FlatWriterRegistryTest { final InstanceIdentifier iid) { return DataObjectUpdate.create(iid, mock(type), mock(type)); } + + //TODO - HONEYCOMB-412 - remove after + /** + * Used to utilize default implementation of canProcess() + * */ + static class CheckedMockWriter implements Writer{ + + private final Writer mockedWriter; + + CheckedMockWriter(final Writer mockedWriter) { + this.mockedWriter = mockedWriter; + } + + @Override + public void processModification(@Nonnull final InstanceIdentifier id, @Nullable final DataObject dataBefore, + @Nullable final DataObject dataAfter, @Nonnull final WriteContext ctx) + throws WriteFailedException { + mockedWriter.processModification(id,dataBefore,dataAfter,ctx); + } + + @Override + public boolean supportsDirectUpdate() { + return mockedWriter.supportsDirectUpdate(); + } + + @Nonnull + @Override + public InstanceIdentifier getManagedDataObjectType() { + return mockedWriter.getManagedDataObjectType(); + } + } } \ No newline at end of file diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/WildcardedSubtreeWriterTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/WildcardedSubtreeWriterTest.java new file mode 100644 index 000000000..7006eeaf4 --- /dev/null +++ b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/write/registry/WildcardedSubtreeWriterTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.translate.impl.write.registry; + +import io.fd.honeycomb.translate.write.Writer; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockitoAnnotations; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.AugTarget; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.FromAugmentAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.FromAugmentListAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.SimpleNestedAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.aug.target.FromAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.aug.target.from.augment.FromAugmentEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.ContainerWithChoice; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.ContainerWithList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.container.with.choice.choice.c3.C3; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.container.with.list.ListInContainer; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.container.with.list.list.in.container.ContainerInList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.container.with.list.list.in.container.container.in.list.NestedList; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class WildcardedSubtreeWriterTest { + + private static final InstanceIdentifier C_WITH_LIST = InstanceIdentifier.create(ContainerWithList.class); + private static final InstanceIdentifier C_WITH_CHOICE = InstanceIdentifier.create(ContainerWithChoice.class); + private static final InstanceIdentifier C_AUG = InstanceIdentifier.create(AugTarget.class); + + private static final InstanceIdentifier L_IN_CONTAINER = C_WITH_LIST.child(ListInContainer.class); + private static final InstanceIdentifier C_IN_LIST = L_IN_CONTAINER.child(ContainerInList.class); + + private static final InstanceIdentifier N_LIST = C_IN_LIST.child(NestedList.class); + + private Writer subtreeContainerWithList; + private Writer subtreeContainerWithChoice; + private Writer subtreeAugTarget; + + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + Writer writerContainerWithList = mock(Writer.class); + Writer writerContainerWithChoice = mock(Writer.class); + Writer writerAugTarget = mock(Writer.class); + when(writerContainerWithList.getManagedDataObjectType()).thenReturn(C_WITH_LIST); + when(writerContainerWithChoice.getManagedDataObjectType()).thenReturn(C_WITH_CHOICE); + when(writerAugTarget.getManagedDataObjectType()).thenReturn(C_AUG); + subtreeContainerWithList = SubtreeWriter.createWildcardedForWriter(writerContainerWithList); + subtreeContainerWithChoice = SubtreeWriter.createWildcardedForWriter(writerContainerWithChoice); + subtreeAugTarget = SubtreeWriter.createWildcardedForWriter(writerAugTarget); + } + + @Test + public void testParent() { + assertTrue(subtreeContainerWithList.canProcess(C_WITH_LIST)); + assertFalse(subtreeContainerWithList.canProcess(C_WITH_CHOICE)); + + assertTrue(subtreeContainerWithChoice.canProcess(C_WITH_CHOICE)); + assertFalse(subtreeContainerWithChoice.canProcess(C_WITH_LIST)); + + assertTrue(subtreeAugTarget.canProcess(C_AUG)); + assertFalse(subtreeAugTarget.canProcess(C_WITH_LIST)); + } + + @Test + public void testDirectChild() { + assertTrue(subtreeContainerWithList.canProcess(L_IN_CONTAINER)); + assertFalse(subtreeContainerWithList.canProcess(C_WITH_CHOICE.child(C3.class))); + + assertTrue(subtreeContainerWithChoice.canProcess(C_WITH_CHOICE.child(C3.class))); + assertFalse(subtreeContainerWithChoice.canProcess(L_IN_CONTAINER)); + } + + @Test + public void testIndirectChild() { + assertTrue(subtreeContainerWithList.canProcess(C_IN_LIST)); + assertTrue(subtreeContainerWithList.canProcess(N_LIST)); + } + + @Test + public void testAugDirectChild() { + assertTrue(subtreeAugTarget.canProcess(C_AUG.augmentation(FromAugmentAugment.class).child(FromAugment.class))); + assertFalse(subtreeContainerWithList.canProcess(C_AUG.augmentation(FromAugmentAugment.class).child(FromAugment.class))); + } + + @Test + public void testAugIndirectChild() { + assertTrue(subtreeAugTarget.canProcess(C_AUG.augmentation(FromAugmentAugment.class) + .child(FromAugment.class) + .augmentation(SimpleNestedAugment.class))); + assertFalse(subtreeContainerWithList.canProcess(C_AUG.augmentation(FromAugmentAugment.class) + .child(FromAugment.class) + .augmentation(FromAugmentListAugment.class) + .child(FromAugmentEntry.class))); + } +} -- cgit 1.2.3-korg