Report ExactDataObjectStep from DataObjectModification
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / LazyAugmentationModification.java
1 /*
2  * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.dom.adapter;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.yangtools.yang.data.tree.api.ModificationType.UNMODIFIED;
12
13 import com.google.common.base.MoreObjects.ToStringHelper;
14 import com.google.common.collect.ImmutableList;
15 import java.util.Collection;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.mdsal.binding.dom.codec.api.BindingAugmentationCodecTreeNode;
19 import org.opendaylight.yangtools.yang.binding.Augmentation;
20 import org.opendaylight.yangtools.yang.binding.ExactDataObjectStep;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
23 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
24
25 /**
26  * Specialization of {@link AbstractDataObjectModification} for {@link Augmentation}s. Is based on a parent
27  * {@link DataTreeCandidateNode}, but contains only a subset of its modifications.
28  */
29 final class LazyAugmentationModification<A extends Augmentation<?>>
30         extends AbstractDataObjectModification<A, BindingAugmentationCodecTreeNode<A>> {
31     private final @NonNull ImmutableList<DataTreeCandidateNode> domChildNodes;
32
33     private LazyAugmentationModification(final BindingAugmentationCodecTreeNode<A> codec,
34             final DataTreeCandidateNode parent, final ImmutableList<DataTreeCandidateNode> domChildNodes) {
35         super(parent, codec, (ExactDataObjectStep<A>) codec.deserializePathArgument(null));
36         this.domChildNodes = requireNonNull(domChildNodes);
37     }
38
39     static <A extends Augmentation<?>> @Nullable LazyAugmentationModification<A> forModifications(
40             final BindingAugmentationCodecTreeNode<A> codec, final DataTreeCandidateNode parent,
41             final Collection<DataTreeCandidateNode> children) {
42         // Filter out any unmodified children first
43         final var domChildren = children.stream()
44             .filter(childMod -> childMod.modificationType() != UNMODIFIED)
45             .collect(ImmutableList.toImmutableList());
46         // Only return a modification if there is something left
47         return domChildren.isEmpty() ? null : new LazyAugmentationModification<>(codec, parent, domChildren);
48     }
49
50     static <A extends Augmentation<?>> @Nullable LazyAugmentationModification<A> forParent(
51             final BindingAugmentationCodecTreeNode<A> codec, final DataTreeCandidateNode parent) {
52         final var builder = ImmutableList.<DataTreeCandidateNode>builder();
53         for (var pathArg : codec.childPathArguments()) {
54             final var child = parent.modifiedChild(pathArg);
55             if (child != null) {
56                 builder.add(child);
57             }
58         }
59         final var domChildren = builder.build();
60         return domChildren.isEmpty() ? null : new LazyAugmentationModification<>(codec, parent, domChildren);
61     }
62
63     @Override
64     ImmutableList<DataTreeCandidateNode> domChildNodes() {
65         return domChildNodes;
66     }
67
68     @Override
69     org.opendaylight.yangtools.yang.data.tree.api.ModificationType domModificationType() {
70         final var before = dataBefore();
71         final var after = dataAfter();
72         if (before == null) {
73             return after == null ? org.opendaylight.yangtools.yang.data.tree.api.ModificationType.UNMODIFIED
74                 :  org.opendaylight.yangtools.yang.data.tree.api.ModificationType.APPEARED;
75         }
76         return after == null ? org.opendaylight.yangtools.yang.data.tree.api.ModificationType.DISAPPEARED
77             : org.opendaylight.yangtools.yang.data.tree.api.ModificationType.SUBTREE_MODIFIED;
78     }
79
80
81     @Override
82     A deserialize(final NormalizedNode normalized) {
83         return codec.filterFrom(normalized);
84     }
85
86     @Override
87     DataTreeCandidateNode firstModifiedChild(final PathArgument arg) {
88         // Not entirely efficient linear search, but otherwise we'd have to index, which is even slower
89         return domChildNodes.stream()
90             .filter(child -> arg.equals(child.name()))
91             .findFirst()
92             .orElse(null);
93     }
94
95     @Override
96     ToStringHelper addToStringAttributes(final ToStringHelper helper) {
97         return super.addToStringAttributes(helper)
98             .add("domType", domData.modificationType())
99             .add("domChildren", domChildNodes);
100     }
101 }