From: Robert Varga Date: Tue, 9 Jan 2024 20:14:59 +0000 (+0100) Subject: Refactor PathArgument to DataObjectStep X-Git-Tag: v13.0.0~37 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=mdsal.git;a=commitdiff_plain;h=889d6606afceea88af3884ee340008c0f8810496 Refactor PathArgument to DataObjectStep InstanceIdentifier.PathArgument is the basic modeling construct for expressing a path composed of DataObject type references. Extract it to a top-level construct, DataObjectStep, which has tree specializations. AbstractPathArgument is kept around for serialization complatibility. This has the nice property of capturing the three possible addressing states, so we can discern them when we see them. Furthermore there is now only YangInstanceIdentifier.PathArgument, which makes for cleaner method signatures and imports. JIRA: MDSAL-815 Change-Id: I22706ccaecae4b70e8afe2644fc74057953c32b0 Signed-off-by: Robert Varga --- diff --git a/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/DataObjectModification.java b/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/DataObjectModification.java index b58fea7bd3..82c1859602 100644 --- a/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/DataObjectModification.java +++ b/binding/mdsal-binding-api/src/main/java/org/opendaylight/mdsal/binding/api/DataObjectModification.java @@ -10,11 +10,13 @@ package org.opendaylight.mdsal.binding.api; import java.util.Collection; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.yangtools.concepts.Identifiable; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.ChildOf; import org.opendaylight.yangtools.yang.binding.ChoiceIn; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; +import org.opendaylight.yangtools.yang.binding.ExactDataObjectStep; import org.opendaylight.yangtools.yang.binding.Key; import org.opendaylight.yangtools.yang.binding.KeyAware; @@ -24,9 +26,7 @@ import org.opendaylight.yangtools.yang.binding.KeyAware; * * @param Type of modified object */ -public interface DataObjectModification extends - org.opendaylight.yangtools.concepts.Identifiable { - +public interface DataObjectModification extends Identifiable> { /** * Represents type of modification which has occurred. */ @@ -46,7 +46,7 @@ public interface DataObjectModification extends } @Override - PathArgument getIdentifier(); + DataObjectStep getIdentifier(); /** * Returns type of modified object. @@ -182,11 +182,10 @@ public interface DataObjectModification extends /** * Returns a child modification if a node identified by {@code childArgument} was modified by this modification. * - * @param childArgument Path Argument of child node - * @return Modification of child identified by {@code childArgument} if {@code childArgument} - * was modified, null otherwise. - * @throws IllegalArgumentException If supplied path argument is not valid child according to - * generated model. + * @param childArgument {@link ExactDataObjectStep} of child node + * @return Modification of child identified by {@code childArgument} if {@code childArgument} was modified, + * {@code null} otherwise + * @throws IllegalArgumentException If supplied step is not valid child according to generated model */ - @Nullable DataObjectModification getModifiedChild(PathArgument childArgument); + @Nullable DataObjectModification getModifiedChild(ExactDataObjectStep childArgument); } diff --git a/binding/mdsal-binding-api/src/test/java/org/opendaylight/mdsal/binding/api/DataTreeIdentifierTest.java b/binding/mdsal-binding-api/src/test/java/org/opendaylight/mdsal/binding/api/DataTreeIdentifierTest.java index f879b96d90..a7e28bab40 100644 --- a/binding/mdsal-binding-api/src/test/java/org/opendaylight/mdsal/binding/api/DataTreeIdentifierTest.java +++ b/binding/mdsal-binding-api/src/test/java/org/opendaylight/mdsal/binding/api/DataTreeIdentifierTest.java @@ -71,7 +71,7 @@ class DataTreeIdentifierTest { } final var bytes = bos.toByteArray(); - assertEquals(450, bytes.length); + assertEquals(342, bytes.length); try (var ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) { assertEquals(TEST_IDENTIFIER1, ois.readObject()); diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractDataObjectModification.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractDataObjectModification.java index 71d306df30..987639da7c 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractDataObjectModification.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/AbstractDataObjectModification.java @@ -36,11 +36,12 @@ import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.ChildOf; import org.opendaylight.yangtools.yang.binding.ChoiceIn; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; +import org.opendaylight.yangtools.yang.binding.ExactDataObjectStep; import org.opendaylight.yangtools.yang.binding.Key; import org.opendaylight.yangtools.yang.binding.KeyAware; +import org.opendaylight.yangtools.yang.binding.KeyStep; +import org.opendaylight.yangtools.yang.binding.NodeStep; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode; @@ -85,7 +86,7 @@ abstract sealed class AbstractDataObjectModification identifier; final @NonNull N codec; @SuppressWarnings("unused") @@ -101,9 +102,9 @@ abstract sealed class AbstractDataObjectModification step) { this.domData = requireNonNull(domData); - this.identifier = requireNonNull(identifier); + identifier = requireNonNull(step); this.codec = requireNonNull(codec); } @@ -124,7 +125,7 @@ abstract sealed class AbstractDataObjectModification getIdentifier() { return identifier; } @@ -189,7 +190,7 @@ abstract sealed class AbstractDataObjectModification getModifiedChild(final PathArgument arg) { + public final DataObjectModification getModifiedChild(final ExactDataObjectStep arg) { final var domArgumentList = new ArrayList(); final var childCodec = codec.bindingPathArgumentChild(arg, domArgumentList); final var toEnter = domArgumentList.iterator(); @@ -225,7 +226,7 @@ abstract sealed class AbstractDataObjectModification & DataObject, C extends ChildOf> List> getModifiedChildren(final Class caseType, final Class childType) { return streamModifiedChildren(childType) - .filter(child -> caseType.equals(child.identifier.getCaseType().orElse(null))) + .filter(child -> caseType.equals(child.identifier.caseType())) .collect(Collectors.toList()); } @@ -251,7 +252,7 @@ abstract sealed class AbstractDataObjectModification & ChildOf, K extends Key> DataObjectModification getModifiedChildListItem(final Class listItem, final K listKey) { - return (DataObjectModification) getModifiedChild(IdentifiableItem.of(listItem, listKey)); + return (DataObjectModification) getModifiedChild(new KeyStep<>(listItem, listKey)); } @Override @@ -259,28 +260,28 @@ abstract sealed class AbstractDataObjectModification & DataObject, C extends KeyAware & ChildOf, K extends Key> DataObjectModification getModifiedChildListItem(final Class caseType, final Class listItem, final K listKey) { - return (DataObjectModification) getModifiedChild(IdentifiableItem.of(caseType, listItem, listKey)); + return (DataObjectModification) getModifiedChild(new KeyStep<>(listItem, caseType, listKey)); } @Override @SuppressWarnings("unchecked") public final > DataObjectModification getModifiedChildContainer( final Class child) { - return (DataObjectModification) getModifiedChild(Item.of(child)); + return (DataObjectModification) getModifiedChild(new NodeStep<>(child)); } @Override @SuppressWarnings("unchecked") public final & DataObject, C extends ChildOf> DataObjectModification getModifiedChildContainer(final Class caseType, final Class child) { - return (DataObjectModification) getModifiedChild(Item.of(caseType, child)); + return (DataObjectModification) getModifiedChild(new NodeStep<>(caseType, child)); } @Override @SuppressWarnings("unchecked") public final & DataObject> DataObjectModification getModifiedAugmentation( final Class augmentation) { - return (DataObjectModification) getModifiedChild(Item.of(augmentation)); + return (DataObjectModification) getModifiedChild(new NodeStep<>(augmentation)); } @Override diff --git a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/DataTreeChangeListenerTest.java b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/DataTreeChangeListenerTest.java index 99867ca96d..58a61e2078 100644 --- a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/DataTreeChangeListenerTest.java +++ b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/DataTreeChangeListenerTest.java @@ -40,19 +40,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.te import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.TwoLevelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.binding.YangModuleInfo; public class DataTreeChangeListenerTest extends AbstractDataBrokerTest { private static final InstanceIdentifier TOP_PATH = InstanceIdentifier.create(Top.class); - private static final PathArgument TOP_ARGUMENT = TOP_PATH.getPathArguments().iterator().next(); + private static final DataObjectStep TOP_ARGUMENT = TOP_PATH.getPathArguments().iterator().next(); private static final InstanceIdentifier FOO_PATH = path(TOP_FOO_KEY); - private static final PathArgument FOO_ARGUMENT = Iterables.getLast(FOO_PATH.getPathArguments()); + private static final DataObjectStep FOO_ARGUMENT = Iterables.getLast(FOO_PATH.getPathArguments()); private static final TopLevelList FOO_DATA = topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_ONE_KEY)); private static final InstanceIdentifier BAR_PATH = path(TOP_BAR_KEY); - private static final PathArgument BAR_ARGUMENT = Iterables.getLast(BAR_PATH.getPathArguments()); + private static final DataObjectStep BAR_ARGUMENT = Iterables.getLast(BAR_PATH.getPathArguments()); private static final TopLevelList BAR_DATA = topLevelList(TOP_BAR_KEY); private static final DataTreeIdentifier TOP_IDENTIFIER = DataTreeIdentifier.of(LogicalDatastoreType.OPERATIONAL, TOP_PATH); @@ -167,8 +167,8 @@ public class DataTreeChangeListenerTest extends AbstractDataBrokerTest { } private static void verifyModification(final DataObjectModification barWrite, - final PathArgument pathArg, final ModificationType eventType) { - assertEquals(pathArg.getType(), barWrite.getDataType()); + final DataObjectStep pathArg, final ModificationType eventType) { + assertEquals(pathArg.type(), barWrite.getDataType()); assertEquals(eventType,barWrite.getModificationType()); assertEquals(pathArg, barWrite.getIdentifier()); } diff --git a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Mdsal298Test.java b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Mdsal298Test.java index d036163baf..956d09756e 100644 --- a/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Mdsal298Test.java +++ b/binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Mdsal298Test.java @@ -50,7 +50,7 @@ import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal298.rev180129.wit import org.opendaylight.yangtools.yang.binding.ChildOf; import org.opendaylight.yangtools.yang.binding.DataRoot; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.NodeStep; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; @@ -106,7 +106,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { .build()); domTx.commit().get(); - final ArgumentCaptor captor = ArgumentCaptor.forClass(Collection.class); + final var captor = ArgumentCaptor.forClass(Collection.class); verify(listener).onDataTreeChanged(captor.capture()); Collection> capture = captor.getValue(); assertEquals(1, capture.size()); @@ -114,7 +114,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { final DataTreeModification change = capture.iterator().next(); assertEquals(CONTAINER_TID, change.getRootPath()); final DataObjectModification changedContainer = change.getRootNode(); - assertEquals(Item.of(Container.class), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(Container.class), changedContainer.getIdentifier()); assertEquals(ModificationType.SUBTREE_MODIFIED, changedContainer.getModificationType()); final Container containerAfter = changedContainer.getDataAfter(); @@ -161,7 +161,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { .build()); domTx.commit().get(); - final ArgumentCaptor captor = ArgumentCaptor.forClass(Collection.class); + final var captor = ArgumentCaptor.forClass(Collection.class); verify(listener).onDataTreeChanged(captor.capture()); Collection> capture = captor.getValue(); assertEquals(1, capture.size()); @@ -169,7 +169,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { final DataTreeModification change = capture.iterator().next(); assertEquals(CONTAINER_TID, change.getRootPath()); final DataObjectModification changedContainer = change.getRootNode(); - assertEquals(Item.of(Container.class), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(Container.class), changedContainer.getIdentifier()); assertEquals(ModificationType.WRITE, changedContainer.getModificationType()); final Container containerAfter = changedContainer.getDataAfter(); @@ -193,7 +193,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { writeTx.put(CONFIGURATION, ADDRESSABLE_CASE, new AddressableBuilder().build()); writeTx.commit().get(); - final ArgumentCaptor captor = ArgumentCaptor.forClass(Collection.class); + final var captor = ArgumentCaptor.forClass(Collection.class); verify(listener).onDataTreeChanged(captor.capture()); Collection> capture = captor.getValue(); assertEquals(1, capture.size()); @@ -202,7 +202,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { assertEquals(CHOICE_CONTAINER_TID, choiceChange.getRootPath()); final DataObjectModification changedContainer = choiceChange.getRootNode(); assertEquals(ModificationType.SUBTREE_MODIFIED, changedContainer.getModificationType()); - assertEquals(Item.of(WithChoice.class), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(WithChoice.class), changedContainer.getIdentifier()); final Collection> choiceChildren = changedContainer.getModifiedChildren(); assertEquals(1, choiceChildren.size()); @@ -210,7 +210,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { final DataObjectModification changedCase = (DataObjectModification) choiceChildren .iterator().next(); assertEquals(ModificationType.WRITE, changedCase.getModificationType()); - assertEquals(Item.of(Addressable.class), changedCase.getIdentifier()); + assertEquals(new NodeStep<>(Addressable.class), changedCase.getIdentifier()); assertEquals(new AddressableBuilder().build(), changedCase.getDataAfter()); } @@ -226,7 +226,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { new AddressableChildBuilder().build()); writeTx.commit().get(); - final ArgumentCaptor captor = ArgumentCaptor.forClass(Collection.class); + final var captor = ArgumentCaptor.forClass(Collection.class); verify(listener).onDataTreeChanged(captor.capture()); Collection> capture = captor.getValue(); assertEquals(1, capture.size()); @@ -235,7 +235,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { assertEquals(ADDRESSABLE_CONTAINER_TID, contChange.getRootPath()); final DataObjectModification changedContainer = contChange.getRootNode(); assertEquals(ModificationType.SUBTREE_MODIFIED, changedContainer.getModificationType()); - assertEquals(Item.of(AddressableCont.class), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(AddressableCont.class), changedContainer.getIdentifier()); final Collection> contChildren = changedContainer.getModifiedChildren(); assertEquals(1, contChildren.size()); @@ -243,7 +243,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { final DataObjectModification changedChild = (DataObjectModification) contChildren .iterator().next(); assertEquals(ModificationType.WRITE, changedChild.getModificationType()); - assertEquals(Item.of(AddressableChild.class), changedChild.getIdentifier()); + assertEquals(new NodeStep<>(AddressableChild.class), changedChild.getIdentifier()); assertEquals(new AddressableChildBuilder().build(), changedChild.getDataAfter()); } @@ -260,7 +260,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { ImmutableNodes.leafNode(BAZ_QNAME, "baz")); domTx.commit().get(); - final ArgumentCaptor captor = ArgumentCaptor.forClass(Collection.class); + final var captor = ArgumentCaptor.forClass(Collection.class); verify(listener).onDataTreeChanged(captor.capture()); Collection> capture = captor.getValue(); assertEquals(1, capture.size()); @@ -269,7 +269,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { assertEquals(UNADDRESSABLE_CONTAINER_TID, contChange.getRootPath()); final DataObjectModification changedContainer = contChange.getRootNode(); assertEquals(ModificationType.WRITE, changedContainer.getModificationType()); - assertEquals(Item.of(UnaddressableCont.class), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(UnaddressableCont.class), changedContainer.getIdentifier()); final Collection> contChildren = changedContainer.getModifiedChildren(); assertEquals(0, contChildren.size()); @@ -292,7 +292,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { .build()); domTx.commit().get(); - final ArgumentCaptor captor = ArgumentCaptor.forClass(Collection.class); + final var captor = ArgumentCaptor.forClass(Collection.class); verify(listener).onDataTreeChanged(captor.capture()); Collection> capture = captor.getValue(); assertEquals(1, capture.size()); @@ -303,7 +303,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { // Should be write assertEquals(ModificationType.WRITE, changedContainer.getModificationType()); - assertEquals(Item.of(WithChoice.class), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(WithChoice.class), changedContainer.getIdentifier()); final Collection> choiceChildren = changedContainer.getModifiedChildren(); assertEquals(0, choiceChildren.size()); @@ -332,7 +332,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { assertEquals(dti, change.getRootPath()); final DataObjectModification changedContainer = change.getRootNode(); assertEquals(ModificationType.WRITE, changedContainer.getModificationType()); - assertEquals(Item.of(bindingClass), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(bindingClass), changedContainer.getIdentifier()); final T containerAfter = changedContainer.getDataAfter(); assertEquals(expected, containerAfter); @@ -359,7 +359,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { .build()); domTx.commit().get(); - final ArgumentCaptor captor = ArgumentCaptor.forClass(Collection.class); + final var captor = ArgumentCaptor.forClass(Collection.class); verify(listener).onDataTreeChanged(captor.capture()); Collection> capture = captor.getValue(); assertEquals(1, capture.size()); @@ -368,7 +368,7 @@ public class Mdsal298Test extends AbstractDataBrokerTest { assertEquals(CHOICE_CONTAINER_TID, change.getRootPath()); final DataObjectModification changedContainer = change.getRootNode(); assertEquals(ModificationType.WRITE, changedContainer.getModificationType()); - assertEquals(Item.of(WithChoice.class), changedContainer.getIdentifier()); + assertEquals(new NodeStep<>(WithChoice.class), changedContainer.getIdentifier()); final WithChoice containerAfter = changedContainer.getDataAfter(); assertEquals(new WithChoiceBuilder().build(), containerAfter); diff --git a/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/BindingDataContainerCodecTreeNode.java b/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/BindingDataContainerCodecTreeNode.java index c2ef310ca4..7ae64f48cf 100644 --- a/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/BindingDataContainerCodecTreeNode.java +++ b/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/BindingDataContainerCodecTreeNode.java @@ -14,9 +14,9 @@ import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.BindingContract; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.common.Empty; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; /** * A {@link BindingObjectCodecTreeNode} which corresponds to a {@link DataContainer} construct. @@ -76,31 +76,26 @@ public non-sealed interface BindingDataContainerCodecTreeNode bindingPathArgumentChild(InstanceIdentifier.@NonNull PathArgument arg, - @Nullable List builder); + @NonNull CommonDataObjectCodecTreeNode bindingPathArgumentChild(@NonNull DataObjectStep step, + @Nullable List builder); /** * Return a summary of addressability of potential children. Binding specification does not allow all DOM tree diff --git a/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/CommonDataObjectCodecTreeNode.java b/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/CommonDataObjectCodecTreeNode.java index e54b7d3a64..05f1734a14 100644 --- a/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/CommonDataObjectCodecTreeNode.java +++ b/binding/mdsal-binding-dom-codec-api/src/main/java/org/opendaylight/mdsal/binding/dom/codec/api/CommonDataObjectCodecTreeNode.java @@ -10,8 +10,10 @@ package org.opendaylight.mdsal.binding.dom.codec.api; import com.google.common.annotations.Beta; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; /** * Common interface shared between {@link BindingDataObjectCodecTreeNode} and {@link BindingAugmentationCodecTreeNode}. @@ -21,27 +23,26 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; */ public interface CommonDataObjectCodecTreeNode extends BindingDataContainerCodecTreeNode { /** - * Serializes path argument for current node. + * Serializes the instance identifier step for current node. * - * @param arg Binding Path Argument, may be null if Binding Instance Identifier does not have a representation for - * current node (e.g. choice or case). - * @return Yang Path Argument, may be null if Yang Instance Identifier does not have representation for current node - * (e.g. case). + * @param step {@link DataObjectStep}, may be null if {@link InstanceIdentifier} does not have a representation for + * current node (e.g. choice or case). + * @return {@link PathArgument}, may be null if {@link YangInstanceIdentifier} does not have representation for + * current node (e.g. case). * @throws IllegalArgumentException If supplied {@code arg} is not valid. */ @Beta - YangInstanceIdentifier.@Nullable PathArgument serializePathArgument(InstanceIdentifier.@Nullable PathArgument arg); + @Nullable PathArgument serializePathArgument(@Nullable DataObjectStep step); /** - * Deserializes path argument for current node. + * Deserializes {@link PathArgument} for current node. * - * @param arg Yang Path Argument, may be null if Yang Instance Identifier does not have - * representation for current node (e.g. case). - * @return Binding Path Argument, may be null if Binding Instance Identifier does not have - * representation for current node (e.g. choice or case). + * @param arg a {@link PathArgument}, may be null if {@link YangInstanceIdentifier} does not have a representation + * for current node (e.g. case). + * @return {@link DataObjectStep}, may be null if {@link InstanceIdentifier} does not have a representation for + * current node (e.g. choice or case). * @throws IllegalArgumentException If supplied {@code arg} is not valid. */ @Beta - InstanceIdentifier.@Nullable PathArgument deserializePathArgument( - YangInstanceIdentifier.@Nullable PathArgument arg); + @Nullable DataObjectStep deserializePathArgument(@Nullable PathArgument arg); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java index 65394235dd..83e9b0f721 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AbstractDataObjectCodecContext.java @@ -17,7 +17,7 @@ import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException; import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; @@ -69,17 +69,17 @@ public abstract sealed class AbstractDataObjectCodecContext bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg, + public final CommonDataObjectCodecContext bindingPathArgumentChild(final DataObjectStep step, final List builder) { - final var argType = arg.getType(); - final var context = childNonNull(pathChildPrototype(argType), argType, - "Class %s is not valid child of %s", argType, getBindingClass()) + final var type = step.type(); + final var context = childNonNull(pathChildPrototype(type), type, + "Class %s is not valid child of %s", type, getBindingClass()) .getCodecContext(); - context.addYangPathArgument(arg, builder); + context.addYangPathArgument(step, builder); if (context instanceof CommonDataObjectCodecContext dataObject) { return dataObject; } else if (context instanceof ChoiceCodecContext choice) { - return choice.bindingPathArgumentChild(arg, builder); + return choice.bindingPathArgumentChild(step, builder); } else { throw new IllegalStateException("Unhandled context " + context); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecContext.java index 3d0e09f59d..d7842638aa 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecContext.java @@ -18,7 +18,7 @@ import org.opendaylight.mdsal.binding.dom.codec.api.BindingAugmentationCodecTree import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; @@ -55,15 +55,15 @@ final class AugmentationCodecContext> } @Override - public PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) { - if (!bindingArg().equals(arg)) { - throw new IllegalArgumentException("Unexpected argument " + arg); + public PathArgument serializePathArgument(final DataObjectStep step) { + if (!bindingArg().equals(step)) { + throw new IllegalArgumentException("Unexpected argument " + step); } return null; } @Override - public InstanceIdentifier.PathArgument deserializePathArgument(final PathArgument arg) { + public DataObjectStep deserializePathArgument(final PathArgument arg) { if (arg != null) { throw new IllegalArgumentException("Unexpected argument " + arg); } @@ -97,7 +97,7 @@ final class AugmentationCodecContext> } @Override - void addYangPathArgument(final List builder, final InstanceIdentifier.PathArgument arg) { + void addYangPathArgument(final List builder, final DataObjectStep step) { // No-op } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java index dccf09ae3c..5f10f1abc5 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationCodecPrototype.java @@ -13,16 +13,16 @@ import com.google.common.collect.ImmutableSet; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.NodeStep; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; final class AugmentationCodecPrototype extends CommonDataObjectCodecPrototype { private final @NonNull ImmutableSet childArgs; @SuppressWarnings("unchecked") - AugmentationCodecPrototype(final Class cls, final AugmentRuntimeType type, final CodecContextFactory factory, - final ImmutableSet childArgs) { - super(Item.of((Class) cls), type, factory); + AugmentationCodecPrototype(final @NonNull Class cls, final AugmentRuntimeType type, + final CodecContextFactory factory, final ImmutableSet childArgs) { + super(new NodeStep<>((Class) cls), type, factory); this.childArgs = requireNonNull(childArgs); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java index 2b351405b4..c6cf57a041 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java @@ -76,6 +76,7 @@ import org.opendaylight.yangtools.yang.binding.BaseNotification; import org.opendaylight.yangtools.yang.binding.ChoiceIn; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.Key; import org.opendaylight.yangtools.yang.binding.KeyAware; @@ -429,23 +430,23 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri @NonNull DataContainerCodecContext getCodecContextNode(final InstanceIdentifier binding, final List builder) { final var it = binding.getPathArguments().iterator(); - final var arg = it.next(); - - DataContainerCodecContext current; - final var caseType = arg.getCaseType(); - if (caseType.isPresent()) { - final @NonNull Class type = caseType.orElseThrow(); - final var choice = choicesByClass.getUnchecked(type); - choice.addYangPathArgument(arg, builder); - final var caze = choice.getStreamChild(type); - caze.addYangPathArgument(arg, builder); - current = caze.bindingPathArgumentChild(arg, builder); + final var step = it.next(); + + final DataContainerCodecContext start; + final var caseType = step.caseType(); + if (caseType != null) { + final var choice = choicesByClass.getUnchecked(caseType); + choice.addYangPathArgument(step, builder); + final var caze = choice.getStreamChild(caseType); + caze.addYangPathArgument(step, builder); + start = caze.bindingPathArgumentChild(step, builder); } else { - final var child = getStreamChild(arg.getType()); - child.addYangPathArgument(arg, builder); - current = child; + final var child = getStreamChild(step.type()); + child.addYangPathArgument(step, builder); + start = child; } + var current = start; while (it.hasNext()) { current = current.bindingPathArgumentChild(it.next(), builder); } @@ -465,7 +466,7 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri * @throws IllegalArgumentException if {@code dom} is empty */ @Nullable BindingDataObjectCodecTreeNode getCodecContextNode(final @NonNull YangInstanceIdentifier dom, - final @Nullable Collection bindingArguments) { + final @Nullable Collection> bindingArguments) { final var it = dom.getPathArguments().iterator(); if (!it.hasNext()) { throw new IllegalArgumentException("Path may not be empty"); @@ -885,7 +886,7 @@ public final class BindingCodecContext extends AbstractBindingNormalizedNodeSeri return null; } - final var builder = new ArrayList(); + final var builder = new ArrayList>(); final var codec = getCodecContextNode(path, builder); if (codec == null) { if (data != null) { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java index 7ae4331218..2bf031865a 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingToNormalizedStreamWriter.java @@ -24,10 +24,10 @@ import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Key; import org.opendaylight.yangtools.yang.binding.KeyAware; import org.opendaylight.yangtools.yang.binding.OpaqueObject; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; @@ -65,7 +65,7 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite } @SuppressWarnings({"unchecked", "rawtypes"}) - private T enter(final Class name, final Class identifier) { + private T enter(final Class name, final Class identifier) { final var current = current(); final CodecContext next; if (current == null) { @@ -80,7 +80,7 @@ final class BindingToNormalizedStreamWriter implements AnydataBindingStreamWrite return identifier.cast(next.getDomPathArgument()); } - private T enter(final String localName, final Class identifier) { + private T enter(final String localName, final Class identifier) { final var current = current(); final var next = ((AbstractDataObjectCodecContext) current).getLeafChild(localName); schema.push(next); diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecContext.java index 11d59e47a0..4e3d7482d3 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CaseCodecContext.java @@ -7,13 +7,11 @@ */ package org.opendaylight.mdsal.binding.dom.codec.impl; -import static com.google.common.base.Preconditions.checkArgument; - import java.util.List; import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -23,7 +21,7 @@ final class CaseCodecContext extends DataObjectCodecContex } @Override - void addYangPathArgument(final List builder, final PathArgument arg) { + void addYangPathArgument(final List builder, final DataObjectStep step) { // NOOP } @@ -38,14 +36,18 @@ final class CaseCodecContext extends DataObjectCodecContex } @Override - public YangInstanceIdentifier.PathArgument serializePathArgument(final PathArgument arg) { - checkArgument(arg == null, "Unexpected argument %s", arg); + public PathArgument serializePathArgument(final DataObjectStep step) { + if (step != null) { + throw new IllegalArgumentException("Unexpected argument " + step); + } return null; } @Override - public PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) { - checkArgument(arg == null, "Unexpected argument %s", arg); + public DataObjectStep deserializePathArgument(final PathArgument arg) { + if (arg != null) { + throw new IllegalArgumentException("Unexpected argument " + arg); + } return null; } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java index 8454de4f25..918b34c5b6 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceCodecContext.java @@ -33,10 +33,10 @@ import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType; import org.opendaylight.yangtools.yang.binding.ChoiceIn; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.binding.contract.Naming; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; @@ -216,7 +216,7 @@ final class ChoiceCodecContext> } @Override - public CodecContext yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) { + public CodecContext yangPathArgumentChild(final PathArgument arg) { return ((CaseCodecContext) super.yangPathArgumentChild(arg)).yangPathArgumentChild(arg); } @@ -241,20 +241,14 @@ final class ChoiceCodecContext> } @Override - public CommonDataObjectCodecContext bindingPathArgumentChild(final PathArgument arg, - final List builder) { - final var caseType = arg.getCaseType(); - final var type = arg.getType(); - final DataContainerCodecContext caze; - if (caseType.isPresent()) { - // Non-ambiguous addressing this should not pose any problems - caze = getStreamChild(caseType.orElseThrow()); - } else { - caze = getCaseByChildClass(type); - } - - caze.addYangPathArgument(arg, builder); - return caze.bindingPathArgumentChild(arg, builder); + public CommonDataObjectCodecContext bindingPathArgumentChild(final DataObjectStep step, + final List builder) { + final var caseType = step.caseType(); + // Prefer non-ambiguous addressing, which should not pose any problems. Otherwise fall back to checking for + // ambiguities + final var caze = caseType != null ? getStreamChild(caseType) : getCaseByChildClass(step.type()); + caze.addYangPathArgument(step, builder); + return caze.bindingPathArgumentChild(step, builder); } private DataContainerCodecContext getCaseByChildClass(final @NonNull Class type) { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecItemFactory.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecItemFactory.java index 10a3248a1c..bc0eb020c9 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecItemFactory.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecItemFactory.java @@ -10,8 +10,8 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static java.util.Objects.requireNonNull; import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.model.api.AddedByUsesAware; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; @@ -25,10 +25,11 @@ sealed class CodecItemFactory { @Override @SuppressWarnings({ "rawtypes", "unchecked" }) - Item createItem(final Class childClass, final EffectiveStatement childSchema) { + DataObjectStep createItem(final Class childClass, final EffectiveStatement childSchema) { // FIXME: MDSAL-697: see overridden method for further guidance return childSchema instanceof AddedByUsesAware aware && aware.isAddedByUses() - ? Item.of((Class) bindingClass, (Class) childClass) : super.createItem(childClass, childSchema); + ? InstanceIdentifier.createStep((Class) bindingClass, (Class) childClass) + : super.createItem(childClass, childSchema); } } @@ -44,9 +45,8 @@ sealed class CodecItemFactory { // receiving childSchema from it via findChildSchemaDefinition, we should be able to receive the equivalent // of Map.Entry, along with the override we create here. One more input we may need to // provide is our bindingClass(). - @SuppressWarnings("unchecked") - Item createItem(final Class childClass, final EffectiveStatement childSchema) { - return Item.of((Class) childClass); + DataObjectStep createItem(final Class childClass, final EffectiveStatement childSchema) { + return InstanceIdentifier.createStep((Class) childClass); } static @NonNull CodecItemFactory of() { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecContext.java index 219ef7ca84..1e38caae1a 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecContext.java @@ -10,8 +10,8 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import org.opendaylight.mdsal.binding.dom.codec.api.CommonDataObjectCodecTreeNode; import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; /** * Base implementation of {@link CommonDataObjectCodecTreeNode}. @@ -27,11 +27,11 @@ abstract sealed class CommonDataObjectCodecContext getBindingPathArgument(final PathArgument domArg) { return bindingArg(); } - protected final PathArgument bindingArg() { + protected final DataObjectStep bindingArg() { return prototype().getBindingArg(); } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java index 0962fea4ad..18e84c33c6 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CommonDataObjectCodecPrototype.java @@ -12,7 +12,7 @@ import static java.util.Objects.requireNonNull; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; /** * Common superclass for {@link DataObjectCodecPrototype} and {@link AugmentationCodecPrototype}. @@ -22,19 +22,20 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; abstract sealed class CommonDataObjectCodecPrototype extends DataContainerPrototype, R> permits AugmentationCodecPrototype, DataObjectCodecPrototype { - private final @NonNull Item bindingArg; + private final @NonNull DataObjectStep step; - CommonDataObjectCodecPrototype(final Item bindingArg, final R runtimeType, final CodecContextFactory factory) { + CommonDataObjectCodecPrototype(final DataObjectStep step, final R runtimeType, + final CodecContextFactory factory) { super(factory, runtimeType); - this.bindingArg = requireNonNull(bindingArg); + this.step = requireNonNull(step); } @Override final Class javaClass() { - return bindingArg.getType(); + return step.type(); } - final @NonNull Item getBindingArg() { - return bindingArg; + final @NonNull DataObjectStep getBindingArg() { + return step; } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java index b906ff3f25..c3fc7ea7e2 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecContext.java @@ -9,7 +9,7 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.NodeStep; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -18,7 +18,7 @@ sealed class ContainerLikeCodecContext permits StructuralContainerCodecContext { ContainerLikeCodecContext(final Class cls, final ContainerLikeRuntimeType type, final CodecContextFactory factory) { - this(new ContainerLikeCodecPrototype(Item.of(cls), type, factory)); + this(new ContainerLikeCodecPrototype(new NodeStep<>(cls), type, factory)); } ContainerLikeCodecContext(final ContainerLikeCodecPrototype prototype) { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java index bfc9f009af..3d7a253be5 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ContainerLikeCodecPrototype.java @@ -8,7 +8,7 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import org.opendaylight.mdsal.binding.runtime.api.ContainerLikeRuntimeType; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; /** @@ -16,9 +16,9 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent */ sealed class ContainerLikeCodecPrototype extends DataObjectCodecPrototype> permits StructuralContainerCodecPrototype { - ContainerLikeCodecPrototype(final Item item, final ContainerLikeRuntimeType type, + ContainerLikeCodecPrototype(final DataObjectStep step, final ContainerLikeRuntimeType type, final CodecContextFactory factory) { - super(item, NodeIdentifier.create(type.statement().argument()), type, factory); + super(step, NodeIdentifier.create(type.statement().argument()), type, factory); } @Override diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java index ebd628c0ff..2848884b27 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java @@ -41,11 +41,11 @@ import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.BindingObject; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder; @@ -114,7 +114,7 @@ abstract sealed class DataContainerCodecContext bindingPathArgumentChild(PathArgument arg, - List builder); + public abstract CommonDataObjectCodecContext bindingPathArgumentChild(DataObjectStep step, + List builder); /** * Serializes supplied Binding Path Argument and adds all necessary YANG instance identifiers to supplied list. * - * @param arg Binding Path Argument + * @param step Binding Path Argument * @param builder DOM Path argument. */ - final void addYangPathArgument(final PathArgument arg, final List builder) { + final void addYangPathArgument(final DataObjectStep step, final List builder) { if (builder != null) { - addYangPathArgument(builder, arg); + addYangPathArgument(builder, step); } } - void addYangPathArgument(final @NonNull List builder, final PathArgument arg) { + void addYangPathArgument(final @NonNull List builder, final DataObjectStep step) { final var yangArg = getDomPathArgument(); if (yangArg != null) { builder.add(yangArg); @@ -178,8 +178,8 @@ abstract sealed class DataContainerCodecContext(context, ImmutableSet.copyOf(cacheSpecifier)); } - protected final @NonNull V childNonNull(final @Nullable V nullable, - final YangInstanceIdentifier.PathArgument child, final String message, final Object... args) { + protected final @NonNull V childNonNull(final @Nullable V nullable, final PathArgument child, + final String message, final Object... args) { if (nullable == null) { throw childNullException(child.getNodeType(), message, args); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java index 8a45102c3b..6ab6c0157b 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java @@ -37,7 +37,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentable; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.BindingObject; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; @@ -307,14 +307,14 @@ public abstract sealed class DataObjectCodecContext deserializePathArgument(final PathArgument arg) { checkArgument(getDomPathArgument().equals(arg)); return bindingArg(); } @Override - public PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) { - checkArgument(bindingArg().equals(arg)); + public PathArgument serializePathArgument(final DataObjectStep step) { + checkArgument(bindingArg().equals(step)); return getDomPathArgument(); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java index e53354f09d..2137b0f2ac 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecPrototype.java @@ -12,7 +12,8 @@ import static java.util.Objects.requireNonNull; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; abstract sealed class DataObjectCodecPrototype extends CommonDataObjectCodecPrototype @@ -24,10 +25,10 @@ abstract sealed class DataObjectCodecPrototype e @SuppressWarnings("unchecked") DataObjectCodecPrototype(final Class cls, final NodeIdentifier yangArg, final T type, final CodecContextFactory factory) { - this(Item.of((Class) cls), yangArg, type, factory); + this(InstanceIdentifier.createStep((Class) cls), yangArg, type, factory); } - DataObjectCodecPrototype(final Item bindingArg, final NodeIdentifier yangArg, final T type, + DataObjectCodecPrototype(final DataObjectStep bindingArg, final NodeIdentifier yangArg, final T type, final CodecContextFactory factory) { super(bindingArg, type, factory); this.yangArg = requireNonNull(yangArg); diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java index 34c8fed782..a8a00d52fc 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/IdentifiableItemCodec.java @@ -22,9 +22,9 @@ import java.util.Map; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.util.ImmutableOffsetMap; import org.opendaylight.yangtools.util.ImmutableOffsetMapTemplate; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; import org.opendaylight.yangtools.yang.binding.Key; import org.opendaylight.yangtools.yang.binding.KeyAware; +import org.opendaylight.yangtools.yang.binding.KeyStep; import org.opendaylight.yangtools.yang.binding.contract.Naming; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; @@ -122,8 +122,8 @@ abstract sealed class IdentifiableItemCodec { private static final Logger LOG = LoggerFactory.getLogger(IdentifiableItemCodec.class); - private final Class identifiable; - private final QName qname; + private final @NonNull Class identifiable; + private final @NonNull QName qname; private IdentifiableItemCodec(final ListEffectiveStatement schema, final Class> keyClass, final Class identifiable) { @@ -145,12 +145,12 @@ abstract sealed class IdentifiableItemCodec { } @SuppressWarnings({ "rawtypes", "unchecked" }) - final @NonNull IdentifiableItem domToBinding(final NodeIdentifierWithPredicates input) { - return IdentifiableItem.of((Class) identifiable, (Key) deserializeIdentifier(requireNonNull(input))); + final @NonNull KeyStep domToBinding(final NodeIdentifierWithPredicates input) { + return new KeyStep(identifiable, deserializeIdentifier(requireNonNull(input))); } - final @NonNull NodeIdentifierWithPredicates bindingToDom(final IdentifiableItem input) { - return serializeIdentifier(qname, input.getKey()); + final @NonNull NodeIdentifierWithPredicates bindingToDom(final KeyStep input) { + return serializeIdentifier(qname, input.key()); } @SuppressWarnings("checkstyle:illegalCatch") diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java index b7f60447f3..587af64a58 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierCodec.java @@ -11,12 +11,12 @@ import static java.util.Objects.requireNonNull; import com.google.common.collect.Iterables; import java.util.ArrayList; -import java.util.List; import org.eclipse.jdt.annotation.NonNull; -import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode; import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec; import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeylessStep; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; @@ -31,12 +31,12 @@ final class InstanceIdentifierCodec implements BindingInstanceIdentifierCodec, @Override public InstanceIdentifier toBinding(final YangInstanceIdentifier domPath) { - final List builder = new ArrayList<>(); - final BindingDataObjectCodecTreeNode codec = context.getCodecContextNode(domPath, builder); + final var builder = new ArrayList>(); + final var codec = context.getCodecContextNode(domPath, builder); if (codec == null) { return null; } - if (codec instanceof ListCodecContext && Iterables.getLast(builder) instanceof InstanceIdentifier.Item) { + if (codec instanceof ListCodecContext && Iterables.getLast(builder) instanceof KeylessStep) { // We ended up in list, but without key, which means it represent list as a whole, // which is not binding representable. return null; @@ -47,7 +47,7 @@ final class InstanceIdentifierCodec implements BindingInstanceIdentifierCodec, @Override public @NonNull YangInstanceIdentifier fromBinding(@NonNull final InstanceIdentifier bindingPath) { - final List domArgs = new ArrayList<>(); + final var domArgs = new ArrayList(); context.getCodecContextNode(bindingPath, domArgs); return YangInstanceIdentifier.of(domArgs); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecContext.java index 7e3019c4be..4023e0d4ae 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecContext.java @@ -14,7 +14,7 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.NodeStep; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -24,7 +24,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode; sealed class ListCodecContext extends DataObjectCodecContext permits MapCodecContext { ListCodecContext(final Class cls, final ListRuntimeType list, final CodecContextFactory factory) { - this(new ListCodecPrototype(Item.of(cls), list, factory)); + this(new ListCodecPrototype(new NodeStep<>(cls), list, factory)); } ListCodecContext(final ListCodecPrototype prototype) { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java index f63eaa27e9..2c6bbdcafd 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ListCodecPrototype.java @@ -8,15 +8,15 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; /** * A prototype for {@link ListCodecContext}. */ sealed class ListCodecPrototype extends DataObjectCodecPrototype permits MapCodecPrototype { - ListCodecPrototype(final Item item, final ListRuntimeType type, final CodecContextFactory factory) { - super(item, NodeIdentifier.create(type.statement().argument()), type, factory); + ListCodecPrototype(final DataObjectStep step, final ListRuntimeType type, final CodecContextFactory factory) { + super(step, NodeIdentifier.create(type.statement().argument()), type, factory); } @Override diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecContext.java index 9b497fce4b..39e8e419bf 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecContext.java @@ -15,15 +15,15 @@ import java.util.Map; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.binding.Key; import org.opendaylight.yangtools.yang.binding.KeyAware; +import org.opendaylight.yangtools.yang.binding.KeyStep; +import org.opendaylight.yangtools.yang.binding.KeylessStep; import org.opendaylight.yangtools.yang.binding.contract.Naming; import org.opendaylight.yangtools.yang.common.Ordering; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; abstract sealed class MapCodecContext, D extends DataObject & KeyAware> @@ -56,9 +56,9 @@ abstract sealed class MapCodecContext, D extends DataObject & K this.codec = requireNonNull(codec); } - static @NonNull MapCodecContext of(final Class cls, final ListRuntimeType type, + static @NonNull MapCodecContext of(final Class cls, final ListRuntimeType type, final CodecContextFactory factory) { - return of(new MapCodecPrototype(Item.of(cls), type, factory)); + return of(new MapCodecPrototype(new KeylessStep(cls), type, factory)); } static @NonNull MapCodecContext of(final MapCodecPrototype prototype) { @@ -78,8 +78,7 @@ abstract sealed class MapCodecContext, D extends DataObject & K } @Override - void addYangPathArgument(final List builder, - final InstanceIdentifier.PathArgument arg) { + void addYangPathArgument(final List builder, final DataObjectStep step) { /* * DOM Instance Identifier for list is always represent by two entries one for map and one for children. This * is also true for wildcarded instance identifiers @@ -87,8 +86,8 @@ abstract sealed class MapCodecContext, D extends DataObject & K final var yangArg = getDomPathArgument(); builder.add(yangArg); - if (arg instanceof IdentifiableItem identifiable) { - builder.add(codec.bindingToDom(identifiable)); + if (step instanceof KeyStep keyStep) { + builder.add(codec.bindingToDom(keyStep)); } else { // Adding wildcarded builder.add(yangArg); @@ -96,15 +95,14 @@ abstract sealed class MapCodecContext, D extends DataObject & K } @Override - protected final InstanceIdentifier.PathArgument getBindingPathArgument( - final YangInstanceIdentifier.PathArgument domArg) { + protected final DataObjectStep getBindingPathArgument(final PathArgument domArg) { return domArg instanceof NodeIdentifierWithPredicates nip ? codec.domToBinding(nip) : super.getBindingPathArgument(domArg); } @SuppressWarnings({ "rawtypes", "unchecked" }) final NodeIdentifierWithPredicates serialize(final Key key) { - return codec.bindingToDom(IdentifiableItem.of((Class)getBindingClass(), (Key)key)); + return codec.bindingToDom(new KeyStep(getBindingClass(), key)); } final @NonNull Key deserialize(final @NonNull NodeIdentifierWithPredicates arg) { @@ -112,14 +110,12 @@ abstract sealed class MapCodecContext, D extends DataObject & K } @Override - public final YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) { - return arg instanceof IdentifiableItem identifiable ? codec.bindingToDom(identifiable) - : super.serializePathArgument(arg); + public final PathArgument serializePathArgument(final DataObjectStep step) { + return step instanceof KeyStep keyStep ? codec.bindingToDom(keyStep) : super.serializePathArgument(step); } @Override - public final InstanceIdentifier.PathArgument deserializePathArgument( - final YangInstanceIdentifier.PathArgument arg) { + public final DataObjectStep deserializePathArgument(final PathArgument arg) { return arg instanceof NodeIdentifierWithPredicates nip ? codec.domToBinding(nip) : super.deserializePathArgument(arg); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java index 58080631b9..c72d4f0966 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MapCodecPrototype.java @@ -10,15 +10,15 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static com.google.common.base.Preconditions.checkArgument; import org.opendaylight.mdsal.binding.runtime.api.ListRuntimeType; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; import org.opendaylight.yangtools.yang.binding.KeyAware; /** * A prototype for a {@link MapCodecContext}. */ final class MapCodecPrototype extends ListCodecPrototype { - MapCodecPrototype(final Item item, final ListRuntimeType type, final CodecContextFactory factory) { - super(item, type, factory); + MapCodecPrototype(final DataObjectStep step, final ListRuntimeType type, final CodecContextFactory factory) { + super(step, type, factory); final var clazz = javaClass(); checkArgument(KeyAware.class.isAssignableFrom(clazz), "%s is not KeyAware", clazz); } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java index dfa7e874cf..ceddb77cda 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecContext.java @@ -13,7 +13,7 @@ import java.lang.invoke.VarHandle; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType; import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.NodeStep; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; /** @@ -37,7 +37,7 @@ final class StructuralContainerCodecContext extends Contai StructuralContainerCodecContext(final Class cls, final ContainerRuntimeType type, final CodecContextFactory factory) { - this(new StructuralContainerCodecPrototype(Item.of(cls), type, factory)); + this(new StructuralContainerCodecPrototype(new NodeStep<>(cls), type, factory)); } StructuralContainerCodecContext(final StructuralContainerCodecPrototype prototype) { diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java index 4fb130c5bf..b41337ff22 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/StructuralContainerCodecPrototype.java @@ -8,15 +8,15 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import org.opendaylight.mdsal.binding.runtime.api.ContainerRuntimeType; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; +import org.opendaylight.yangtools.yang.binding.DataObjectStep; /** * A prototype for a {@link StructuralContainerCodecContext}. */ final class StructuralContainerCodecPrototype extends ContainerLikeCodecPrototype { - StructuralContainerCodecPrototype(final Item item, final ContainerRuntimeType container, + StructuralContainerCodecPrototype(final DataObjectStep step, final ContainerRuntimeType container, final CodecContextFactory factory) { - super(item, container, factory); + super(step, container, factory); } @Override diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java index 8050fadf34..ae62ab8acc 100644 --- a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java +++ b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/InstanceIdentifierSerializeDeserializeTest.java @@ -14,6 +14,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import com.google.common.collect.Iterables; import org.junit.Test; @@ -34,7 +35,7 @@ import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.con import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.grp.GrpCont; import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.root.RootBase; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.Key; +import org.opendaylight.yangtools.yang.binding.KeyStep; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; @@ -75,8 +76,7 @@ public class InstanceIdentifierSerializeDeserializeTest extends AbstractBindingC final var last = Iterables.getLast(instanceIdentifier.getPathArguments()); assertEquals(TopLevelList.class, instanceIdentifier.getTargetType()); assertFalse(instanceIdentifier.isWildcarded()); - assertTrue(last instanceof InstanceIdentifier.IdentifiableItem); - final Key key = ((InstanceIdentifier.IdentifiableItem) last).getKey(); + final var key = assertInstanceOf(KeyStep.class, last).key(); assertEquals(TopLevelListKey.class, key.getClass()); assertEquals(TOP_LEVEL_LIST_KEY_VALUE, ((TopLevelListKey)key).getName()); } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectStep.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectStep.java new file mode 100644 index 0000000000..2926ba3319 --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectStep.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.binding; + +import java.io.Serializable; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +/** + * A reference to a {@link DataObject} type forming a single step in a path similar to {@code instance-identifier}. + * + * @param DataObject type + */ +/* + * FIXME: this interface forms a partial model of the following RFC7950 construct: + * + * ;; Instance Identifiers + * + * instance-identifier = 1*("/" (node-identifier [1*key-predicate / leaf-list-predicate / pos])) + * + * We handle the 'node-identifier for DataObjects' and 'key-predicate' cases. What is missing are interfaces for: + * - 'leaf-list-predicate' (exact value match) + * - 'pos' interfaces (index into a list or a leaf-list} + * - 'node-identifier for non-DataObjects' (i.e. leaf, anydata, anyxml) + */ +public sealed interface DataObjectStep extends Comparable>, Serializable + permits ExactDataObjectStep, KeylessStep { + /** + * Return the data object type backing this PathArgument. + * + * @return Data object type + */ + @NonNull Class type(); + + /** + * Return an optional enclosing case type. This is used only when {@link #type()} references a node defined + * in a {@code grouping} which is reference inside a {@code case} statement in order to safely reference the node. + * + * @return case class, or {@code null} + */ + @Nullable Class caseType(); + + @Override + default int compareTo(final DataObjectStep other) { + final var typeCmp = compareClasses(type(), other.type()); + if (typeCmp != 0) { + return typeCmp; + } + final var caseType = caseType(); + final var otherCaseType = other.caseType(); + if (caseType == null) { + return otherCaseType == null ? 0 : -1; + } + final var caseCmp = otherCaseType == null ? 1 : compareClasses(caseType, otherCaseType); + return caseCmp != 0 ? caseCmp : compareHierarchy(this, other); + } + + private static int compareHierarchy(final DataObjectStep recv, final DataObjectStep other) { + if (recv instanceof NodeStep) { + if (other instanceof NodeStep) { + return 0; + } else if (other instanceof KeylessStep || other instanceof KeyStep) { + return -1; + } + } else if (recv instanceof KeyStep thisAware) { + if (other instanceof KeyStep otherAware) { + @SuppressWarnings("unchecked") + final var thisKey = (Comparable) thisAware.key(); + return thisKey.compareTo(otherAware.key()); + } else if (other instanceof NodeStep || other instanceof KeylessStep) { + return 1; + } + } else if (recv instanceof KeylessStep) { + if (other instanceof KeylessStep) { + return 0; + } else if (other instanceof NodeStep || other instanceof KeyStep) { + return 1; + } + } + throw new IllegalStateException("Unhandled " + recv + ".compareTo(" + other + ")"); + } + + private static int compareClasses(final Class first, final Class second) { + return first.getCanonicalName().compareTo(second.getCanonicalName()); + } +} diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/ExactDataObjectStep.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/ExactDataObjectStep.java new file mode 100644 index 0000000000..34541f21a5 --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/ExactDataObjectStep.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.binding; + +/** + * A {@link DataObjectStep} which is exactly specified. Due to how {@link DataObject} and {@link KeyAware} are tied + * together, a class generated for a {@code list} is strictly a {@link DataObject}, but its semantics differ. + * + *

+ * This interface captures two possible outcomes: + *

    + *
  1. this is a plain {@link NodeStep}
  2. + *
  3. this is a fully-specified {@link KeyStep}
  4. + *
+ * + * @param DataObject type + */ +public sealed interface ExactDataObjectStep extends DataObjectStep + permits KeyStep, NodeStep { + // for class hierarchy only +} \ No newline at end of file diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/IIv4.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/IIv4.java new file mode 100644 index 0000000000..59cd94b03f --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/IIv4.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.binding; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.ObjectStreamException; +import org.eclipse.jdt.annotation.Nullable; + +sealed class IIv4 implements Externalizable permits KIIv4 { + @java.io.Serial + private static final long serialVersionUID = 1L; + + private @Nullable Iterable> pathArguments; + private @Nullable Class targetType; + private boolean wildcarded; + private int hash; + + @SuppressWarnings("redundantModifier") + public IIv4() { + // For Externalizable + } + + IIv4(final InstanceIdentifier source) { + pathArguments = source.pathArguments; + targetType = source.getTargetType(); + wildcarded = source.isWildcarded(); + hash = source.hashCode(); + } + + final int getHash() { + return hash; + } + + final Iterable> getPathArguments() { + return pathArguments; + } + + final Class getTargetType() { + return targetType; + } + + final boolean isWildcarded() { + return wildcarded; + } + + @Override + public void writeExternal(final ObjectOutput out) throws IOException { + out.writeObject(targetType); + out.writeBoolean(wildcarded); + out.writeInt(hash); + out.writeInt(Iterables.size(pathArguments)); + for (var o : pathArguments) { + out.writeObject(o); + } + } + + @Override + public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { + targetType = (Class) in.readObject(); + wildcarded = in.readBoolean(); + hash = in.readInt(); + + final int size = in.readInt(); + final var builder = ImmutableList.>builderWithExpectedSize(size); + for (int i = 0; i < size; ++i) { + builder.add((DataObjectStep) in.readObject()); + } + pathArguments = builder.build(); + } + + @java.io.Serial + Object readResolve() throws ObjectStreamException { + return new InstanceIdentifier<>(targetType, pathArguments, wildcarded, hash); + } +} diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java index da23b8fc0c..22681a4d0f 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java @@ -12,6 +12,7 @@ import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; +import com.google.common.annotations.Beta; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.VerifyException; @@ -24,10 +25,8 @@ import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Objects; -import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.yangtools.concepts.HierarchicalIdentifier; @@ -38,23 +37,20 @@ import org.opendaylight.yangtools.util.HashCodeBuilder; * *

* For Example let's say you were trying to refer to a node in inventory which was modeled in YANG as follows, + *

code{
+ *   module opendaylight-inventory {
+ *     ....
  *
- * 

- *

- * module opendaylight-inventory {
- *      ....
- *
- *      container nodes {
- *        list node {
- *            key "id";
- *            ext:context-instance "node-context";
- *
- *            uses node;
- *        }
- *    }
+ *     container nodes {
+ *       list node {
+ *         key "id";
+ *         ext:context-instance "node-context";
  *
- * }
- * 
+ * uses node; + * } + * } + * } + * }
* *

* You can create an instance identifier as follows to get to a node with id "openflow:1": {@code @@ -64,8 +60,9 @@ import org.opendaylight.yangtools.util.HashCodeBuilder; *

* This would be the same as using a path like so, "/nodes/node/openflow:1" to refer to the openflow:1 node */ -public class InstanceIdentifier - implements HierarchicalIdentifier> { +public sealed class InstanceIdentifier + implements HierarchicalIdentifier> + permits KeyedInstanceIdentifier { @java.io.Serial private static final long serialVersionUID = 3L; @@ -73,13 +70,13 @@ public class InstanceIdentifier * Protected to differentiate internal and external access. Internal access is required never to modify * the contents. References passed to outside entities have to be wrapped in an unmodifiable view. */ - final Iterable pathArguments; + final Iterable> pathArguments; private final @NonNull Class targetType; private final boolean wildcarded; private final int hash; - InstanceIdentifier(final Class type, final Iterable pathArguments, final boolean wildcarded, + InstanceIdentifier(final Class type, final Iterable> pathArguments, final boolean wildcarded, final int hash) { this.pathArguments = requireNonNull(pathArguments); targetType = requireNonNull(type); @@ -115,7 +112,7 @@ public class InstanceIdentifier * * @return Path argument chain. Immutable and does not contain nulls. */ - public final @NonNull Iterable getPathArguments() { + public final @NonNull Iterable> getPathArguments() { return Iterables.unmodifiableIterable(pathArguments); } @@ -145,43 +142,24 @@ public class InstanceIdentifier return false; } - final InstanceIdentifier other = (InstanceIdentifier) obj; + final var other = (InstanceIdentifier) obj; if (pathArguments == other.pathArguments) { return true; } /* - * We could now just go and compare the pathArguments, but that - * can be potentially expensive. Let's try to avoid that by - * checking various things that we have cached from pathArguments - * and trying to prove the identifiers are *not* equal. + * We could now just go and compare the pathArguments, but that can be potentially expensive. Let's try to avoid + * that by checking various things that we have cached from pathArguments and trying to prove the identifiers + * are *not* equal. */ - if (hash != other.hash) { - return false; - } - if (wildcarded != other.wildcarded) { - return false; - } - if (targetType != other.targetType) { - return false; - } - if (fastNonEqual(other)) { - return false; - } - - // Everything checks out so far, so we have to do a full equals - return Iterables.elementsEqual(pathArguments, other.pathArguments); + return hash == other.hash && wildcarded == other.wildcarded && targetType == other.targetType + && keyEquals(other) + // Everything checks out so far, so we have to do a full equals + && Iterables.elementsEqual(pathArguments, other.pathArguments); } - /** - * Perform class-specific fast checks for non-equality. This allows subclasses to avoid iterating over the - * pathArguments by performing quick checks on their specific fields. - * - * @param other The other identifier, guaranteed to be the same class - * @return true if the other identifier cannot be equal to this one. - */ - protected boolean fastNonEqual(final InstanceIdentifier other) { - return false; + boolean keyEquals(final InstanceIdentifier other) { + return true; } @Override @@ -224,11 +202,10 @@ public class InstanceIdentifier public final @Nullable InstanceIdentifier firstIdentifierOf( final Class<@NonNull I> type) { int count = 1; - for (final PathArgument a : pathArguments) { - if (type.equals(a.getType())) { + for (var step : pathArguments) { + if (type.equals(step.type())) { @SuppressWarnings("unchecked") - final InstanceIdentifier ret = (InstanceIdentifier) internalCreate( - Iterables.limit(pathArguments, count)); + final var ret = (InstanceIdentifier) internalCreate(Iterables.limit(pathArguments, count)); return ret; } @@ -248,14 +225,13 @@ public class InstanceIdentifier */ public final & DataObject, K extends Key> @Nullable K firstKeyOf( final Class<@NonNull N> listItem) { - for (final PathArgument i : pathArguments) { - if (listItem.equals(i.getType())) { + for (var step : pathArguments) { + if (step instanceof KeyStep keyPredicate && listItem.equals(step.type())) { @SuppressWarnings("unchecked") - final K ret = ((IdentifiableItem)i).getKey(); + final var ret = (K) keyPredicate.key(); return ret; } } - return null; } @@ -283,18 +259,15 @@ public class InstanceIdentifier public final boolean contains(final InstanceIdentifier other) { requireNonNull(other, "other should not be null"); - final Iterator oit = other.pathArguments.iterator(); - - for (PathArgument pathArgument : pathArguments) { + final var oit = other.pathArguments.iterator(); + for (var step : pathArguments) { if (!oit.hasNext()) { return false; } - - if (!pathArgument.equals(oit.next())) { + if (!step.equals(oit.next())) { return false; } } - return true; } @@ -309,27 +282,30 @@ public class InstanceIdentifier public final boolean containsWildcarded(final InstanceIdentifier other) { requireNonNull(other, "other should not be null"); - final Iterator oit = other.pathArguments.iterator(); - - for (PathArgument la : pathArguments) { - if (!oit.hasNext()) { + final var otherSteps = other.pathArguments.iterator(); + for (var step : pathArguments) { + if (!otherSteps.hasNext()) { return false; } - final PathArgument oa = oit.next(); - - if (!la.getType().equals(oa.getType())) { - return false; - } - if (la instanceof IdentifiableItem && oa instanceof IdentifiableItem && !la.equals(oa)) { - return false; + final var otherStep = otherSteps.next(); + if (step instanceof ExactDataObjectStep) { + if (!step.equals(otherStep)) { + return false; + } + } else if (step instanceof KeylessStep keyless) { + if (!keyless.matches(otherStep)) { + return false; + } + } else { + throw new IllegalStateException("Unhandled step " + step); } } return true; } - private @NonNull InstanceIdentifier childIdentifier(final AbstractPathArgument arg) { + private @NonNull InstanceIdentifier childIdentifier(final DataObjectStep arg) { return trustedCreate(arg, Iterables.concat(pathArguments, Collections.singleton(arg)), HashCodeBuilder.nextHashCode(hash, arg), wildcarded); } @@ -345,7 +321,7 @@ public class InstanceIdentifier */ public final > @NonNull InstanceIdentifier child( final Class<@NonNull N> container) { - return childIdentifier(Item.of(container)); + return childIdentifier(createStep(container)); } /** @@ -362,7 +338,7 @@ public class InstanceIdentifier @SuppressWarnings("unchecked") public final & ChildOf, K extends Key> @NonNull KeyedInstanceIdentifier child(final Class<@NonNull N> listItem, final K listKey) { - return (KeyedInstanceIdentifier) childIdentifier(IdentifiableItem.of(listItem, listKey)); + return (KeyedInstanceIdentifier) childIdentifier(new KeyStep<>(listItem, listKey)); } /** @@ -379,7 +355,7 @@ public class InstanceIdentifier // FIXME: add a proper caller public final & DataObject, N extends ChildOf> @NonNull InstanceIdentifier child(final Class<@NonNull C> caze, final Class<@NonNull N> container) { - return childIdentifier(Item.of(caze, container)); + return childIdentifier(createStep(caze, container)); } /** @@ -400,7 +376,7 @@ public class InstanceIdentifier public final & DataObject, K extends Key, N extends KeyAware & ChildOf> @NonNull KeyedInstanceIdentifier child( final Class<@NonNull C> caze, final Class<@NonNull N> listItem, final K listKey) { - return (KeyedInstanceIdentifier) childIdentifier(IdentifiableItem.of(caze, listItem, listKey)); + return (KeyedInstanceIdentifier) childIdentifier(new KeyStep<>(listItem, requireNonNull(caze), listKey)); } /** @@ -414,12 +390,12 @@ public class InstanceIdentifier */ public final > @NonNull InstanceIdentifier augmentation( final Class<@NonNull N> container) { - return childIdentifier(Item.of(container)); + return childIdentifier(new NodeStep<>(container)); } @java.io.Serial - private Object writeReplace() throws ObjectStreamException { - return new InstanceIdentifierV3<>(this); + Object writeReplace() throws ObjectStreamException { + return new IIv4<>(this); } @java.io.Serial @@ -461,7 +437,7 @@ public class InstanceIdentifier */ public static > @NonNull Builder builder( final Class container) { - return new RegularBuilder<>(Item.of(container)); + return new RegularBuilder<>(createStep(container)); } /** @@ -477,7 +453,7 @@ public class InstanceIdentifier */ public static & DataObject, T extends ChildOf> @NonNull Builder builder(final Class caze, final Class container) { - return new RegularBuilder<>(Item.of(caze, container)); + return new RegularBuilder<>(createStep(caze, container)); } /** @@ -493,7 +469,7 @@ public class InstanceIdentifier public static & ChildOf, K extends Key> @NonNull KeyedBuilder builder(final Class listItem, final K listKey) { - return new KeyedBuilder<>(IdentifiableItem.of(listItem, listKey)); + return new KeyedBuilder<>(new KeyStep<>(listItem, listKey)); } /** @@ -513,13 +489,13 @@ public class InstanceIdentifier N extends KeyAware & ChildOf, K extends Key> @NonNull KeyedBuilder builder(final Class caze, final Class listItem, final K listKey) { - return new KeyedBuilder<>(IdentifiableItem.of(caze, listItem, listKey)); + return new KeyedBuilder<>(new KeyStep<>(listItem, requireNonNull(caze), listKey)); } public static > @NonNull Builder builderOfInherited(final Class root, final Class container) { // FIXME: we are losing root identity, hence namespaces may not work correctly - return new RegularBuilder<>(Item.of(container)); + return new RegularBuilder<>(createStep(container)); } public static & DataObject, @@ -527,7 +503,7 @@ public class InstanceIdentifier @NonNull Builder builderOfInherited(final Class root, final Class caze, final Class container) { // FIXME: we are losing root identity, hence namespaces may not work correctly - return new RegularBuilder<>(Item.of(caze, container)); + return new RegularBuilder<>(createStep(caze, container)); } public static & ChildOf, @@ -535,7 +511,7 @@ public class InstanceIdentifier @NonNull KeyedBuilder builderOfInherited(final Class root, final Class listItem, final K listKey) { // FIXME: we are losing root identity, hence namespaces may not work correctly - return new KeyedBuilder<>(IdentifiableItem.of(listItem, listKey)); + return new KeyedBuilder<>(new KeyStep<>(listItem, listKey)); } public static & DataObject, @@ -543,7 +519,19 @@ public class InstanceIdentifier @NonNull KeyedBuilder builderOfInherited(final Class root, final Class caze, final Class listItem, final K listKey) { // FIXME: we are losing root identity, hence namespaces may not work correctly - return new KeyedBuilder<>(IdentifiableItem.of(caze, listItem, listKey)); + return new KeyedBuilder<>(new KeyStep<>(listItem, requireNonNull(caze), listKey)); + } + + @Beta + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static & DataObject> @NonNull DataObjectStep createStep( + final Class caze, final Class type) { + return KeyAware.class.isAssignableFrom(type) ? new KeylessStep(type, caze) : new NodeStep<>(type, caze); + } + + @Beta + public static @NonNull DataObjectStep createStep(final Class type) { + return createStep(null, type); } /** @@ -555,24 +543,24 @@ public class InstanceIdentifier * @throws IllegalArgumentException if pathArguments is empty or contains a null element. * @throws NullPointerException if {@code pathArguments} is null */ - private static @NonNull InstanceIdentifier internalCreate(final Iterable pathArguments) { + private static @NonNull InstanceIdentifier internalCreate(final Iterable> pathArguments) { final var it = requireNonNull(pathArguments, "pathArguments may not be null").iterator(); checkArgument(it.hasNext(), "pathArguments may not be empty"); - final HashCodeBuilder hashBuilder = new HashCodeBuilder<>(); + final var hashBuilder = new HashCodeBuilder>(); boolean wildcard = false; - PathArgument arg; + DataObjectStep arg; do { arg = it.next(); // Non-null is implied by our callers - final var type = verifyNotNull(arg).getType(); + final var type = verifyNotNull(arg).type(); checkArgument(ChildOf.class.isAssignableFrom(type) || Augmentation.class.isAssignableFrom(type), "%s is not a valid path argument", type); hashBuilder.addArgument(arg); - if (KeyAware.class.isAssignableFrom(type) && !(arg instanceof IdentifiableItem)) { + if (!(arg instanceof ExactDataObjectStep)) { wildcard = true; } } while (it.hasNext()); @@ -581,7 +569,7 @@ public class InstanceIdentifier } /** - * Create an instance identifier for a sequence of {@link PathArgument} steps. The steps are required to be formed + * Create an instance identifier for a sequence of {@link DataObjectStep} steps. The steps are required to be formed * of classes extending either {@link ChildOf} or {@link Augmentation} contracts. This method does not check whether * or not the sequence is structurally sound, for example that an {@link Augmentation} follows an * {@link Augmentable} step. Furthermore the compile-time indicated generic type of the returned object does not @@ -599,7 +587,7 @@ public class InstanceIdentifier */ @SuppressWarnings("unchecked") public static @NonNull InstanceIdentifier unsafeOf( - final List pathArguments) { + final List> pathArguments) { return (InstanceIdentifier) internalCreate(ImmutableList.copyOf(pathArguments)); } @@ -620,7 +608,7 @@ public class InstanceIdentifier @SuppressWarnings("unchecked") public static > @NonNull InstanceIdentifier create( final Class<@NonNull T> type) { - return (InstanceIdentifier) internalCreate(ImmutableList.of(Item.of(type))); + return (InstanceIdentifier) internalCreate(ImmutableList.of(createStep(type))); } /** @@ -643,88 +631,90 @@ public class InstanceIdentifier } @SuppressWarnings({ "unchecked", "rawtypes" }) - static @NonNull InstanceIdentifier trustedCreate(final PathArgument arg, - final Iterable pathArguments, final int hash, final boolean wildcarded) { - if (arg instanceof IdentifiableItem identifiable) { - return new KeyedInstanceIdentifier(arg.getType(), pathArguments, wildcarded, hash, identifiable.getKey()); + static @NonNull InstanceIdentifier trustedCreate(final DataObjectStep lastStep, + final Iterable> pathArguments, final int hash, final boolean wildcarded) { + if (lastStep instanceof NodeStep) { + return new InstanceIdentifier(lastStep.type(), pathArguments, wildcarded, hash); + } else if (lastStep instanceof KeyStep predicate) { + return new KeyedInstanceIdentifier(predicate, pathArguments, wildcarded, hash); + } else if (lastStep instanceof KeylessStep) { + return new InstanceIdentifier(lastStep.type(), pathArguments, true, hash); + } else { + throw new IllegalStateException("Unhandled step " + lastStep); } - - final var type = arg.getType(); - return new InstanceIdentifier(type, pathArguments, wildcarded || KeyAware.class.isAssignableFrom(type), - hash); } - /** - * Path argument of {@link InstanceIdentifier}. Interface which implementations are used as path components of the - * path in overall data tree. - */ - public interface PathArgument extends Comparable { + @Deprecated(since = "13.0.0", forRemoval = true) + private abstract static sealed class AbstractPathArgument + implements Comparable>, Serializable { + @java.io.Serial + private static final long serialVersionUID = 1L; + + private final @NonNull Class type; + + AbstractPathArgument(final Class type) { + this.type = requireNonNull(type, "Type may not be null."); + } + /** * Return the data object type backing this PathArgument. * * @return Data object type. */ - @NonNull Class getType(); + final @NonNull Class type() { + return type; + } /** - * Return an optional enclosing case type. This is used only when {@link #getType()} references a node defined + * Return an optional enclosing case type. This is used only when {@link #type()} references a node defined * in a {@code grouping} which is reference inside a {@code case} statement in order to safely reference the * node. * - * @return Optional case class. + * @return case class or {@code null} */ - default Optional> getCaseType() { - return Optional.empty(); - } - } - - private abstract static class AbstractPathArgument implements PathArgument, Serializable { - @java.io.Serial - private static final long serialVersionUID = 1L; - - private final @NonNull Class type; - - AbstractPathArgument(final Class type) { - this.type = requireNonNull(type, "Type may not be null."); - } - - @Override - public final Class getType() { - return type; + Class caseType() { + return null; } - Object getKey() { + @Nullable Object key() { return null; } @Override public final int hashCode() { - return Objects.hash(type, getCaseType(), getKey()); + return Objects.hash(type, caseType(), key()); } @Override public final boolean equals(final Object obj) { return this == obj || obj instanceof AbstractPathArgument other && type.equals(other.type) - && Objects.equals(getKey(), other.getKey()) && getCaseType().equals(other.getCaseType()); + && Objects.equals(key(), other.key()) && Objects.equals(caseType(), other.caseType()); } @Override - public final int compareTo(final PathArgument arg) { - final int cmp = compareClasses(type, arg.getType()); + public final int compareTo(final AbstractPathArgument arg) { + final int cmp = compareClasses(type, arg.type()); if (cmp != 0) { return cmp; } - final Optional> caseType = getCaseType(); - if (!caseType.isPresent()) { - return arg.getCaseType().isPresent() ? -1 : 1; + final var caseType = caseType(); + final var argCaseType = arg.caseType(); + if (caseType == null) { + return argCaseType == null ? 1 : -1; } - final Optional> argCaseType = getCaseType(); - return argCaseType.isPresent() ? compareClasses(caseType.orElseThrow(), argCaseType.orElseThrow()) : 1; + return argCaseType == null ? 1 : compareClasses(caseType, argCaseType); } private static int compareClasses(final Class first, final Class second) { return first.getCanonicalName().compareTo(second.getCanonicalName()); } + + @java.io.Serial + final Object readResolve() throws ObjectStreamException { + return toStep(); + } + + abstract DataObjectStep toStep(); } /** @@ -733,7 +723,8 @@ public class InstanceIdentifier * * @param Item type */ - public static class Item extends AbstractPathArgument { + @Deprecated(since = "13.0.0", forRemoval = true) + private static sealed class Item extends AbstractPathArgument { @java.io.Serial private static final long serialVersionUID = 1L; @@ -741,37 +732,15 @@ public class InstanceIdentifier super(type); } - /** - * Return a PathArgument instance backed by the specified class. - * - * @param type Backing class - * @param Item type - * @return A new PathArgument - * @throws NullPointerException if {@code} is null. - */ - public static @NonNull Item of(final Class type) { - return new Item<>(type); - } - - /** - * Return a PathArgument instance backed by the specified class, which in turn is defined in a {@code grouping} - * used in a corresponding {@code case} statement. - * - * @param caseType defining case class - * @param type Backing class - * @param Case type - * @param Item type - * @return A new PathArgument - * @throws NullPointerException if any argument is null. - */ - public static & DataObject, T extends ChildOf> @NonNull Item of( - final Class caseType, final Class type) { - return new CaseItem<>(caseType, type); + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + final DataObjectStep toStep() { + return createStep((Class) caseType(), type()); } @Override public String toString() { - return getType().getName(); + return type().getName(); } } @@ -782,7 +751,8 @@ public class InstanceIdentifier * @param An object that is identifiable by an identifier * @param The identifier of the object */ - public static class IdentifiableItem & DataObject, T extends Key> + @Deprecated(since = "13.0.0", forRemoval = true) + private static sealed class IdentifiableItem & DataObject, T extends Key> extends AbstractPathArgument { @java.io.Serial private static final long serialVersionUID = 1L; @@ -794,55 +764,28 @@ public class InstanceIdentifier this.key = requireNonNull(key, "Key may not be null."); } - /** - * Return an IdentifiableItem instance backed by the specified class with specified key. - * - * @param type Backing class - * @param key Key - * @param List type - * @param Key type - * @return An IdentifiableItem - * @throws NullPointerException if any argument is null. - */ - public static & DataObject, I extends Key> - @NonNull IdentifiableItem of(final Class type, final I key) { - return new IdentifiableItem<>(type, key); - } - - /** - * Return an IdentifiableItem instance backed by the specified class with specified key. The class is in turn - * defined in a {@code grouping} used in a corresponding {@code case} statement. - * - * @param caseType defining case class - * @param type Backing class - * @param Case type - * @param List type - * @param Key type - * @return A new PathArgument - * @throws NullPointerException if any argument is null. - */ - public static & DataObject, T extends ChildOf & KeyAware, - I extends Key> @NonNull IdentifiableItem of(final Class caseType, - final Class type, final I key) { - return new CaseIdentifiableItem<>(caseType, type, key); - } - /** * Return the data object type backing this PathArgument. * * @return Data object type. */ @Override - public final @NonNull T getKey() { + final @NonNull T key() { return key; } + @Override + final KeyStep toStep() { + return new KeyStep<>(type(), caseType(), key); + } + @Override public String toString() { - return getType().getName() + "[key=" + key + "]"; + return type().getName() + "[key=" + key + "]"; } } + @Deprecated(since = "13.0.0", forRemoval = true) private static final class CaseItem & DataObject, T extends ChildOf> extends Item { @java.io.Serial @@ -856,11 +799,12 @@ public class InstanceIdentifier } @Override - public Optional> getCaseType() { - return Optional.of(caseType); + Class caseType() { + return caseType; } } + @Deprecated(since = "13.0.0", forRemoval = true) private static final class CaseIdentifiableItem & DataObject, T extends ChildOf & KeyAware, K extends Key> extends IdentifiableItem { @java.io.Serial @@ -874,8 +818,8 @@ public class InstanceIdentifier } @Override - public Optional> getCaseType() { - return Optional.of(caseType); + Class caseType() { + return caseType; } } @@ -885,18 +829,18 @@ public class InstanceIdentifier * @param Instance identifier target type */ public abstract static sealed class Builder { - private final ImmutableList.Builder pathBuilder; - private final HashCodeBuilder hashBuilder; - private final Iterable basePath; + private final ImmutableList.Builder> pathBuilder; + private final HashCodeBuilder> hashBuilder; + private final Iterable> basePath; private boolean wildcard; - Builder(final Builder prev, final PathArgument item, final boolean isWildcard) { + Builder(final Builder prev, final DataObjectStep item) { pathBuilder = prev.pathBuilder; hashBuilder = prev.hashBuilder; basePath = prev.basePath; wildcard = prev.wildcard; - appendItem(item, isWildcard); + appendItem(item); } Builder(final InstanceIdentifier identifier) { @@ -906,7 +850,7 @@ public class InstanceIdentifier basePath = identifier.pathArguments; } - Builder(final PathArgument item, final boolean wildcard) { + Builder(final DataObjectStep item, final boolean wildcard) { pathBuilder = ImmutableList.builder(); hashBuilder = new HashCodeBuilder<>(); basePath = null; @@ -930,7 +874,7 @@ public class InstanceIdentifier */ public final > Builder augmentation( final Class container) { - return append(Item.of(container), false); + return append(new NodeStep<>(container)); } /** @@ -951,7 +895,7 @@ public class InstanceIdentifier * @throws NullPointerException if {@code container} is null */ public final > Builder child(final Class container) { - return append(Item.of(container), KeyAware.class.isAssignableFrom(container)); + return append(createStep(container)); } /** @@ -968,7 +912,7 @@ public class InstanceIdentifier */ public final & DataObject, N extends ChildOf> Builder child( final Class caze, final Class container) { - return append(Item.of(caze, container), KeyAware.class.isAssignableFrom(container)); + return append(createStep(caze, container)); } /** @@ -985,7 +929,7 @@ public class InstanceIdentifier */ public final & ChildOf, K extends Key> KeyedBuilder child( final Class<@NonNull N> listItem, final K listKey) { - return append(IdentifiableItem.of(listItem, listKey)); + return append(new KeyStep<>(listItem, listKey)); } /** @@ -1005,7 +949,7 @@ public class InstanceIdentifier public final & DataObject, K extends Key, N extends KeyAware & ChildOf> KeyedBuilder child(final Class caze, final Class listItem, final K listKey) { - return append(IdentifiableItem.of(caze, listItem, listKey)); + return append(new KeyStep<>(listItem, requireNonNull(caze), listKey)); } /** @@ -1027,40 +971,42 @@ public class InstanceIdentifier && Iterables.elementsEqual(pathArguments(), other.pathArguments()); } - final Iterable pathArguments() { + final Iterable> pathArguments() { final var args = pathBuilder.build(); return basePath == null ? args : Iterables.concat(basePath, args); } - final void appendItem(final PathArgument item, final boolean isWildcard) { + final void appendItem(final DataObjectStep item) { hashBuilder.addArgument(item); pathBuilder.add(item); - wildcard |= isWildcard; + if (!(item instanceof ExactDataObjectStep)) { + wildcard = true; + } } - abstract @NonNull RegularBuilder append(Item item, boolean isWildcard); + abstract @NonNull RegularBuilder append(DataObjectStep step); - abstract , Y extends Key> - @NonNull KeyedBuilder append(IdentifiableItem item); + abstract , Y extends Key> @NonNull KeyedBuilder append( + KeyStep step); } public static final class KeyedBuilder, K extends Key> extends Builder { - private @NonNull IdentifiableItem lastItem; + private @NonNull KeyStep lastStep; - KeyedBuilder(final IdentifiableItem item) { - super(item, false); - lastItem = requireNonNull(item); + KeyedBuilder(final KeyStep firstStep) { + super(firstStep, false); + lastStep = requireNonNull(firstStep); } KeyedBuilder(final KeyedInstanceIdentifier identifier) { super(identifier); - lastItem = IdentifiableItem.of(identifier.getTargetType(), identifier.getKey()); + lastStep = identifier.lastStep(); } - private KeyedBuilder(final RegularBuilder prev, final IdentifiableItem item) { - super(prev, item, false); - lastItem = requireNonNull(item); + private KeyedBuilder(final RegularBuilder prev, final KeyStep lastStep) { + super(prev, lastStep); + this.lastStep = requireNonNull(lastStep); } /** @@ -1070,21 +1016,19 @@ public class InstanceIdentifier */ @Override public @NonNull KeyedInstanceIdentifier build() { - return new KeyedInstanceIdentifier<>(lastItem.getType(), pathArguments(), wildcard(), hashCode(), - lastItem.getKey()); + return new KeyedInstanceIdentifier<>(lastStep, pathArguments(), wildcard(), hashCode()); } @Override - @NonNull RegularBuilder append(final Item item, final boolean isWildcard) { - return new RegularBuilder<>(this, item, isWildcard); + @NonNull RegularBuilder append(final DataObjectStep step) { + return new RegularBuilder<>(this, step); } @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - , Y extends Key> KeyedBuilder append( - final IdentifiableItem item) { - appendItem(item, false); - lastItem = (IdentifiableItem) item; + @SuppressWarnings("unchecked") + , Y extends Key> KeyedBuilder append(final KeyStep step) { + appendItem(step); + lastStep = (KeyStep) requireNonNull(step); return (KeyedBuilder) this; } } @@ -1092,9 +1036,9 @@ public class InstanceIdentifier private static final class RegularBuilder extends Builder { private @NonNull Class type; - RegularBuilder(final Item item) { - super(item, KeyAware.class.isAssignableFrom(item.getType())); - type = item.getType(); + RegularBuilder(final DataObjectStep item) { + super(item, !(item instanceof ExactDataObjectStep)); + type = item.type(); } RegularBuilder(final InstanceIdentifier identifier) { @@ -1102,9 +1046,9 @@ public class InstanceIdentifier type = identifier.getTargetType(); } - private RegularBuilder(final KeyedBuilder prev, final Item item, final boolean wildcard) { - super(prev, item, wildcard); - type = item.getType(); + private RegularBuilder(final KeyedBuilder prev, final DataObjectStep item) { + super(prev, item); + type = item.type(); } @Override @@ -1114,15 +1058,15 @@ public class InstanceIdentifier @Override @SuppressWarnings({ "rawtypes", "unchecked" }) - RegularBuilder append(final Item item, final boolean isWildcard) { - appendItem(item, isWildcard); - type = (Class) item.getType(); + RegularBuilder append(final DataObjectStep step) { + appendItem(step); + type = (Class) step.type(); return (RegularBuilder) this; } @Override , Y extends Key> KeyedBuilder append( - final IdentifiableItem item) { + final KeyStep item) { return new KeyedBuilder<>(this, item); } } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierV3.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierV3.java index 80fcf14441..4158b1f3c2 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierV3.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierV3.java @@ -8,23 +8,20 @@ package org.opendaylight.yangtools.yang.binding; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; import java.io.Externalizable; import java.io.IOException; +import java.io.NotSerializableException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; import java.io.Serial; -import java.util.ArrayList; -import java.util.List; import org.eclipse.jdt.annotation.Nullable; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; class InstanceIdentifierV3 implements Externalizable { @Serial private static final long serialVersionUID = 3L; - private @Nullable Iterable pathArguments; + private @Nullable Iterable> pathArguments; private @Nullable Class targetType; private boolean wildcarded; private int hash; @@ -34,18 +31,11 @@ class InstanceIdentifierV3 implements Externalizable { // For Externalizable } - InstanceIdentifierV3(final InstanceIdentifier source) { - pathArguments = source.pathArguments; - targetType = source.getTargetType(); - wildcarded = source.isWildcarded(); - hash = source.hashCode(); - } - final int getHash() { return hash; } - final Iterable getPathArguments() { + final Iterable> getPathArguments() { return pathArguments; } @@ -59,13 +49,7 @@ class InstanceIdentifierV3 implements Externalizable { @Override public void writeExternal(final ObjectOutput out) throws IOException { - out.writeObject(targetType); - out.writeBoolean(wildcarded); - out.writeInt(hash); - out.writeInt(Iterables.size(pathArguments)); - for (Object o : pathArguments) { - out.writeObject(o); - } + throw new NotSerializableException(InstanceIdentifierV3.class.getName()); } @Override @@ -75,14 +59,14 @@ class InstanceIdentifierV3 implements Externalizable { hash = in.readInt(); final int size = in.readInt(); - final List args = new ArrayList<>(); + final var builder = ImmutableList.>builderWithExpectedSize(size); for (int i = 0; i < size; ++i) { - args.add((PathArgument) in.readObject()); + builder.add((DataObjectStep) in.readObject()); } - pathArguments = ImmutableList.copyOf(args); + pathArguments = builder.build(); } - @Serial + @java.io.Serial Object readResolve() throws ObjectStreamException { return new InstanceIdentifier<>(targetType, pathArguments, wildcarded, hash); } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KIIv4.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KIIv4.java new file mode 100644 index 0000000000..3cb9087e93 --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KIIv4.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.binding; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.ObjectStreamException; + +final class KIIv4 & DataObject, K extends Key> extends IIv4 { + @java.io.Serial + private static final long serialVersionUID = 2L; + + private K key; + + @SuppressWarnings("redundantModifier") + public KIIv4() { + // For Externalizable + } + + KIIv4(final KeyedInstanceIdentifier source) { + super(source); + key = source.getKey(); + } + + @Override + public void writeExternal(final ObjectOutput out) throws IOException { + super.writeExternal(out); + out.writeObject(key); + } + + @Override + public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + key = (K) in.readObject(); + } + + @java.io.Serial + @Override + Object readResolve() throws ObjectStreamException { + return new KeyedInstanceIdentifier<>(new KeyStep<>(getTargetType(), key), getPathArguments(), + isWildcarded(), getHash()); + } +} diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyStep.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyStep.java new file mode 100644 index 0000000000..ed002cc749 --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyStep.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.binding; + +import static java.util.Objects.requireNonNull; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +/** + * A {@link KeyAware}-based step with a {@link #key()}. It equates to a {@code node-identifier} with a + * {@code key-predicate}. + * + * @param Key type + * @param KeyAware type + */ +public record KeyStep, T extends KeyAware & DataObject>( + @NonNull Class type, + @Nullable Class caseType, + @NonNull K key) implements ExactDataObjectStep, KeyAware { + @java.io.Serial + private static final long serialVersionUID = 0; + + public KeyStep { + NodeStep.checkType(type, true); + NodeStep.checkCaseType(caseType); + requireNonNull(key); + } + + public KeyStep(final @NonNull Class type, final @NonNull K key) { + this(type, null, key); + } +} diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java index ecbc48aeb6..ebd5cd258b 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java @@ -8,7 +8,6 @@ package org.opendaylight.yangtools.yang.binding; import java.io.ObjectStreamException; -import java.io.Serial; import org.eclipse.jdt.annotation.NonNull; /** @@ -17,17 +16,21 @@ import org.eclipse.jdt.annotation.NonNull; * @param Target data type * @param Target key type */ -public class KeyedInstanceIdentifier & DataObject, K extends Key> +public final class KeyedInstanceIdentifier & DataObject, K extends Key> extends InstanceIdentifier { - @Serial + @java.io.Serial private static final long serialVersionUID = 2L; - private final K key; + private final @NonNull KeyStep lastStep; - KeyedInstanceIdentifier(final Class<@NonNull T> type, final Iterable pathArguments, - final boolean wildcarded, final int hash, final K key) { - super(type, pathArguments, wildcarded, hash); - this.key = key; + KeyedInstanceIdentifier(final KeyStep lastStep, final Iterable> pathArguments, + final boolean wildcarded, final int hash) { + super(lastStep.type(), pathArguments, wildcarded, hash); + this.lastStep = lastStep; + } + + @NonNull KeyStep lastStep() { + return lastStep; } /** @@ -36,29 +39,22 @@ public class KeyedInstanceIdentifier & DataObject, K exten * * @return Key associated with this instance identifier. */ - public final K getKey() { - return key; + public @NonNull K getKey() { + return lastStep.key(); } @Override - public final KeyedBuilder builder() { + public KeyedBuilder builder() { return new KeyedBuilder<>(this); } @Override - protected boolean fastNonEqual(final InstanceIdentifier other) { - final KeyedInstanceIdentifier kii = (KeyedInstanceIdentifier) other; - - /* - * We could do an equals() here, but that may actually be expensive. - * equals() in superclass falls back to a full compare, which will - * end up running that equals anyway, so do not bother here. - */ - return key == null != (kii.key == null); + boolean keyEquals(final InstanceIdentifier other) { + return getKey().equals(((KeyedInstanceIdentifier) other).getKey()); } - @Serial - private Object writeReplace() throws ObjectStreamException { - return new KeyedInstanceIdentifierV2<>(this); + @Override + Object writeReplace() throws ObjectStreamException { + return new KIIv4<>(this); } } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierV2.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierV2.java index df19d31ff6..a9f718298d 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierV2.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierV2.java @@ -12,25 +12,19 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; import java.io.Serial; -import org.eclipse.jdt.annotation.Nullable; final class KeyedInstanceIdentifierV2 & DataObject, K extends Key> extends InstanceIdentifierV3 { - @Serial + @java.io.Serial private static final long serialVersionUID = 2L; - private @Nullable K key; + private K key; @SuppressWarnings("redundantModifier") public KeyedInstanceIdentifierV2() { // For Externalizable } - KeyedInstanceIdentifierV2(final KeyedInstanceIdentifier source) { - super(source); - key = source.getKey(); - } - @Override public void writeExternal(final ObjectOutput out) throws IOException { super.writeExternal(out); @@ -46,6 +40,7 @@ final class KeyedInstanceIdentifierV2 & DataObject, K exte @Serial @Override Object readResolve() throws ObjectStreamException { - return new KeyedInstanceIdentifier<>(getTargetType(), getPathArguments(), isWildcarded(), getHash(), key); + return new KeyedInstanceIdentifier<>(new KeyStep<>(getTargetType(), key), getPathArguments(), + isWildcarded(), getHash()); } } diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeylessStep.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeylessStep.java new file mode 100644 index 0000000000..8d1fce011f --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeylessStep.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.binding; + +import java.util.Objects; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +/** + * A {@link KeyAware}-based step without the corresponding key. This corresponds to a {@code node-identifier} step, + * where we know there is a {@code key-predicate} possible, but we do not have it. + * + * @param KeyAware type + */ +public record KeylessStep & DataObject>( + @NonNull Class type, + @Nullable Class caseType) implements DataObjectStep { + @java.io.Serial + private static final long serialVersionUID = 0; + + public KeylessStep { + NodeStep.checkType(type, true); + NodeStep.checkCaseType(caseType); + } + + public KeylessStep(final @NonNull Class type) { + this(type, null); + } + + boolean matches(final @NonNull DataObjectStep other) { + // FIXME: this should be an instanceof check for KeyStep, then a match -- i.e. reject match on plain NodeStep, + // because that is an addressing mismatch + return type.equals(other.type()) && Objects.equals(caseType, other.caseType()); + } +} diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/NodeStep.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/NodeStep.java new file mode 100644 index 0000000000..d14fbf213b --- /dev/null +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/NodeStep.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.binding; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; + +/** + * A {@link DataObject}-based step along an {@code instance-identifier}. It equates to a {@code node-identifier} and + * carries additional assertion that there are no valid predicates for this type. + * + * @param DataObject type + */ +public record NodeStep( + @NonNull Class type, + @Nullable Class caseType) implements ExactDataObjectStep { + @java.io.Serial + private static final long serialVersionUID = 0; + + public NodeStep { + checkType(type, false); + checkCaseType(caseType); + } + + public NodeStep(final @NonNull Class type) { + this(type, null); + } + + static void checkType(final Class type, final boolean keyAware) { + if (!DataObject.class.isAssignableFrom(type) || KeyAware.class.isAssignableFrom(type) != keyAware) { + throw new IllegalArgumentException("Invalid type " + type); + } + } + + static void checkCaseType(final @Nullable Class caseType) { + if (caseType != null && !DataObject.class.isAssignableFrom(caseType)) { + throw new IllegalArgumentException("Invalid case type " + caseType); + } + } +} diff --git a/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java b/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java index b560e84da6..bf173a65ab 100644 --- a/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java +++ b/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java @@ -14,7 +14,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableList; @@ -183,9 +182,9 @@ public class InstanceIdentifierTest { @Test public void keyOfTest() { - final Key identifier = mock(Key.class); - assertEquals(identifier, InstanceIdentifier.keyOf( - new KeyedInstanceIdentifier(KeyAware.class, ImmutableList.of(), false, 0, identifier))); + final var key = new NodeKey(42); + assertEquals(key, InstanceIdentifier.keyOf( + new KeyedInstanceIdentifier<>(new KeyStep<>(Node.class, key), ImmutableList.of(), false, 0))); } @Test diff --git a/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierTest.java b/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierTest.java index 466b168a00..f9531a8f0b 100644 --- a/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierTest.java +++ b/binding/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifierTest.java @@ -8,25 +8,24 @@ package org.opendaylight.yangtools.yang.binding; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; import com.google.common.collect.ImmutableList; import org.junit.Test; +import org.opendaylight.yangtools.yang.binding.test.mock.Node; +import org.opendaylight.yangtools.yang.binding.test.mock.NodeKey; public class KeyedInstanceIdentifierTest { - @Test public void basicTest() { - final Key key = mock(Key.class); - final KeyedInstanceIdentifier keyedInstanceIdentifier = - new KeyedInstanceIdentifier(KeyAware.class, ImmutableList.of(), false, 0, key); + final var key = new NodeKey(0); + final var keyed = new KeyedInstanceIdentifier<>(new KeyStep<>(Node.class, key), ImmutableList.of(), + false, 0); - assertEquals(key, keyedInstanceIdentifier.getKey()); + assertEquals(key, keyed.getKey()); + assertTrue(keyed.keyEquals(keyed.builder().build())); - assertFalse(keyedInstanceIdentifier.fastNonEqual(keyedInstanceIdentifier.builder().build())); - assertTrue(new KeyedInstanceIdentifier(KeyAware.class, ImmutableList.of(), false, 0, null) - .fastNonEqual(keyedInstanceIdentifier.builder().build())); + final var keyless = new InstanceIdentifier<>(Node.class, ImmutableList.of(), true, 0); + assertTrue(keyless.keyEquals(keyed.builder().build())); } } \ No newline at end of file diff --git a/trace/mdsal-trace-impl/src/main/java/org/opendaylight/mdsal/trace/impl/TracingBroker.java b/trace/mdsal-trace-impl/src/main/java/org/opendaylight/mdsal/trace/impl/TracingBroker.java index 641e185d1b..49df6240bd 100644 --- a/trace/mdsal-trace-impl/src/main/java/org/opendaylight/mdsal/trace/impl/TracingBroker.java +++ b/trace/mdsal-trace-impl/src/main/java/org/opendaylight/mdsal/trace/impl/TracingBroker.java @@ -233,8 +233,8 @@ public class TracingBroker implements TracingDOMDataBroker { } static void toPathString(final InstanceIdentifier iid, final StringBuilder builder) { - for (InstanceIdentifier.PathArgument pathArg : iid.getPathArguments()) { - builder.append('/').append(pathArg.getType().getSimpleName()); + for (var pathArg : iid.getPathArguments()) { + builder.append('/').append(pathArg.type().getSimpleName()); } }