From 0caa84f6453e1c45dd9e6f3972c95a6b813cc146 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 3 Sep 2023 21:17:45 +0200 Subject: [PATCH] Seal ModificationApplyOperation We have a carefully-structured class hierarchy here. Make sure the JVM understands it when performing partial loading. Change-Id: Ie4b50be7127c7b103a84212d4674f017b1a9e5bc Signed-off-by: Robert Varga --- ...ractNodeContainerModificationStrategy.java | 9 ++-- .../data/tree/impl/AbstractValidation.java | 3 +- .../impl/ContainerModificationStrategy.java | 39 +++++++++++++--- ...DataNodeContainerModificationStrategy.java | 6 +-- .../impl/MapEntryModificationStrategy.java | 2 +- .../tree/impl/ModificationApplyOperation.java | 3 +- .../tree/impl/SchemaAwareApplyOperation.java | 5 ++- ...ructuralContainerModificationStrategy.java | 45 ------------------- 8 files changed, 51 insertions(+), 61 deletions(-) delete mode 100644 data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/StructuralContainerModificationStrategy.java diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractNodeContainerModificationStrategy.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractNodeContainerModificationStrategy.java index 24743f88f6..5a43bfdd28 100644 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractNodeContainerModificationStrategy.java +++ b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractNodeContainerModificationStrategy.java @@ -34,9 +34,11 @@ import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode; import org.opendaylight.yangtools.yang.data.tree.impl.node.Version; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -abstract class AbstractNodeContainerModificationStrategy +abstract sealed class AbstractNodeContainerModificationStrategy extends SchemaAwareApplyOperation { - abstract static class Invisible extends AbstractNodeContainerModificationStrategy { + abstract static sealed class Invisible + extends AbstractNodeContainerModificationStrategy + permits LeafSetModificationStrategy, MapModificationStrategy { private final @NonNull SchemaAwareApplyOperation entryStrategy; Invisible(final NormalizedNodeContainerSupport support, final DataTreeConfiguration treeConfig, @@ -60,7 +62,8 @@ abstract class AbstractNodeContainerModificationStrategy extends AbstractNodeContainerModificationStrategy { + abstract static sealed class Visible extends AbstractNodeContainerModificationStrategy + permits ChoiceModificationStrategy, DataNodeContainerModificationStrategy { private final @NonNull T schema; Visible(final NormalizedNodeContainerSupport support, final DataTreeConfiguration treeConfig, diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractValidation.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractValidation.java index de2488fb78..1055cbc09a 100644 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractValidation.java +++ b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/AbstractValidation.java @@ -25,7 +25,8 @@ import org.slf4j.LoggerFactory; * A forwarding {@link ModificationApplyOperation}. Useful for strategies which do not deal with data layout, but rather * perform additional validation. */ -abstract class AbstractValidation extends ModificationApplyOperation { +abstract sealed class AbstractValidation extends ModificationApplyOperation + permits MinMaxElementsValidation, UniqueValidation { private static final Logger LOG = LoggerFactory.getLogger(AbstractValidation.class); private final @NonNull ModificationApplyOperation delegate; diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ContainerModificationStrategy.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ContainerModificationStrategy.java index 1e5574bddf..906b9eed5b 100644 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ContainerModificationStrategy.java +++ b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ContainerModificationStrategy.java @@ -14,6 +14,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.DistinctNodeContainer; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration; import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode; @@ -26,8 +27,8 @@ import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; * with mandatory nodes, as it needs to tap into {@link SchemaAwareApplyOperation}'s operations, or subclassed * for the purposes of {@link StructuralContainerModificationStrategy}'s automatic lifecycle. */ -class ContainerModificationStrategy extends DataNodeContainerModificationStrategy { - private static final class EnforcingMandatory extends ContainerModificationStrategy { +sealed class ContainerModificationStrategy extends DataNodeContainerModificationStrategy { + static final class EnforcingMandatory extends ContainerModificationStrategy { private final MandatoryLeafEnforcer enforcer; EnforcingMandatory(final ContainerSchemaNode schemaNode, final DataTreeConfiguration treeConfig, @@ -66,6 +67,35 @@ class ContainerModificationStrategy extends DataNodeContainerModificationStrateg } } + /** + * Structural containers are special in that they appear when implied by child nodes and disappear whenever they are + * empty. We could implement this as a subclass of {@link SchemaAwareApplyOperation}, but the automatic semantic + * is quite different from all the other strategies. We create a {@link ContainerModificationStrategy} to tap into + * that logic, but wrap it so we only call out into it. We do not use {@link PresenceContainerModificationStrategy} + * because it enforces presence of mandatory leaves, which is not something we want here, as structural containers + * are not root anchors for that validation. + */ + static final class Structural extends ContainerModificationStrategy { + private final ContainerNode emptyNode; + + Structural(final ContainerLike schema, final DataTreeConfiguration treeConfig) { + super(schema, treeConfig); + emptyNode = ImmutableNodes.containerNode(schema.getQName()); + } + + @Override + Optional apply(final ModifiedNode modification, + final Optional storeMeta, final Version version) { + return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, storeMeta, + version); + } + + @Override + TreeNode defaultTreeNode() { + return defaultTreeNode(emptyNode); + } + } + private static final NormalizedNodeContainerSupport SUPPORT = new NormalizedNodeContainerSupport<>(ContainerNode.class, ImmutableContainerNodeBuilder::create, ImmutableContainerNodeBuilder::create); @@ -74,13 +104,12 @@ class ContainerModificationStrategy extends DataNodeContainerModificationStrateg super(SUPPORT, schemaNode, treeConfig); } - static ModificationApplyOperation of(final ContainerSchemaNode schema, final DataTreeConfiguration treeConfig) { + static ContainerModificationStrategy of(final ContainerSchemaNode schema, final DataTreeConfiguration treeConfig) { if (schema.isPresenceContainer()) { final var enforcer = MandatoryLeafEnforcer.forContainer(schema, treeConfig); return enforcer != null ? new EnforcingMandatory(schema, treeConfig, enforcer) : new ContainerModificationStrategy(schema, treeConfig); } - - return new StructuralContainerModificationStrategy(schema, treeConfig); + return new Structural(schema, treeConfig); } } diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/DataNodeContainerModificationStrategy.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/DataNodeContainerModificationStrategy.java index ae29c3e835..8aa7321ed0 100644 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/DataNodeContainerModificationStrategy.java +++ b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/DataNodeContainerModificationStrategy.java @@ -23,12 +23,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Base strategy for applying changes to a ContainerNode, irrespective of its - * actual type. + * Base strategy for applying changes to a ContainerNode, irrespective of its actual type. * * @param Type of the container node */ -class DataNodeContainerModificationStrategy extends Visible { +sealed class DataNodeContainerModificationStrategy extends Visible + permits ContainerModificationStrategy, MapEntryModificationStrategy { private static final Logger LOG = LoggerFactory.getLogger(DataNodeContainerModificationStrategy.class); private static final VarHandle CHILDREN; diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/MapEntryModificationStrategy.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/MapEntryModificationStrategy.java index 2015259c04..0a35aeec91 100644 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/MapEntryModificationStrategy.java +++ b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/MapEntryModificationStrategy.java @@ -21,7 +21,7 @@ import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode; import org.opendaylight.yangtools.yang.data.tree.impl.node.Version; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; -class MapEntryModificationStrategy extends DataNodeContainerModificationStrategy { +sealed class MapEntryModificationStrategy extends DataNodeContainerModificationStrategy { private static final class EnforcingMandatory extends MapEntryModificationStrategy { private final MandatoryLeafEnforcer enforcer; diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ModificationApplyOperation.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ModificationApplyOperation.java index 32f990cb10..1688d66f78 100644 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ModificationApplyOperation.java +++ b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/ModificationApplyOperation.java @@ -42,7 +42,8 @@ import org.opendaylight.yangtools.yang.data.tree.impl.node.Version; * * */ -abstract class ModificationApplyOperation implements StoreTreeNode { +abstract sealed class ModificationApplyOperation implements StoreTreeNode + permits AbstractValidation, SchemaAwareApplyOperation { /** * Implementation of this operation must be stateless and must not change state of this object. * diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/SchemaAwareApplyOperation.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/SchemaAwareApplyOperation.java index 8be123f28c..9f97c637b7 100644 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/SchemaAwareApplyOperation.java +++ b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/SchemaAwareApplyOperation.java @@ -38,7 +38,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -abstract class SchemaAwareApplyOperation extends ModificationApplyOperation { +abstract sealed class SchemaAwareApplyOperation extends ModificationApplyOperation + permits AbstractNodeContainerModificationStrategy, ListModificationStrategy, ValueNodeModificationStrategy { private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareApplyOperation.class); static ModificationApplyOperation from(final DataSchemaNode schemaNode, @@ -61,7 +62,7 @@ abstract class SchemaAwareApplyOperation extends Modif } else if (schemaNode instanceof AnyxmlSchemaNode anyxml) { return new ValueNodeModificationStrategy<>(AnyxmlNode.class, anyxml); } else if (schemaNode instanceof SchemaContext context) { - return new StructuralContainerModificationStrategy(context, treeConfig); + return new ContainerModificationStrategy.Structural(context, treeConfig); } else { throw new IllegalStateException("Unsupported schema " + schemaNode); } diff --git a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/StructuralContainerModificationStrategy.java b/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/StructuralContainerModificationStrategy.java deleted file mode 100644 index 01c4570082..0000000000 --- a/data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/StructuralContainerModificationStrategy.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2015 Cisco Systems, Inc. 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.data.tree.impl; - -import java.util.Optional; -import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; -import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; -import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration; -import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode; -import org.opendaylight.yangtools.yang.data.tree.impl.node.Version; -import org.opendaylight.yangtools.yang.model.api.ContainerLike; - -/** - * Structural containers are special in that they appear when implied by child nodes and disappear whenever they are - * empty. We could implement this as a subclass of {@link SchemaAwareApplyOperation}, but the automatic semantic - * is quite different from all the other strategies. We create a {@link ContainerModificationStrategy} to tap into that - * logic, but wrap it so we only call out into it. We do not use {@link PresenceContainerModificationStrategy} because - * it enforces presence of mandatory leaves, which is not something we want here, as structural containers are not - * root anchors for that validation. - */ -final class StructuralContainerModificationStrategy extends ContainerModificationStrategy { - private final ContainerNode emptyNode; - - StructuralContainerModificationStrategy(final ContainerLike schema, final DataTreeConfiguration treeConfig) { - super(schema, treeConfig); - this.emptyNode = ImmutableNodes.containerNode(schema.getQName()); - } - - @Override - Optional apply(final ModifiedNode modification, final Optional storeMeta, - final Version version) { - return AutomaticLifecycleMixin.apply(super::apply, this::applyWrite, emptyNode, modification, storeMeta, - version); - } - - @Override - TreeNode defaultTreeNode() { - return defaultTreeNode(emptyNode); - } -} -- 2.36.6