Define a feature-parent
[yangtools.git] / data / yang-data-tree-ri / src / main / java / org / opendaylight / yangtools / yang / data / tree / impl / OperationWithModification.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.yangtools.yang.data.tree.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.Optional;
13 import org.eclipse.jdt.annotation.Nullable;
14 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
15 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
16 import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode;
17 import org.opendaylight.yangtools.yang.data.tree.impl.node.Version;
18
19 final class OperationWithModification {
20     private final ModificationApplyOperation applyOperation;
21     private final ModifiedNode modification;
22
23     private OperationWithModification(final ModificationApplyOperation op, final ModifiedNode mod) {
24         applyOperation = requireNonNull(op);
25         modification = requireNonNull(mod);
26     }
27
28     void write(final NormalizedNode value) {
29         modification.write(value);
30         /**
31          * Fast validation of structure, full validation on written data will be run during seal.
32          */
33         applyOperation.quickVerifyStructure(value);
34     }
35
36     void merge(final NormalizedNode data, final Version version) {
37         /*
38          * A merge operation will end up overwriting parts of the tree, retaining others. We want to
39          * make sure we do not validate the complete resulting structure, but rather just what was
40          * written. In order to do that, we first pretend the data was written, run verification and
41          * then perform the merge -- with the explicit assumption that adding the newly-validated
42          * data with the previously-validated data will not result in invalid data.
43          *
44          * We perform only quick validation here, full validation will be applied as-needed during
45          * preparation, as the merge is reconciled with current state.
46          */
47         applyOperation.quickVerifyStructure(data);
48         applyOperation.mergeIntoModifiedNode(modification, data, version);
49     }
50
51     void delete() {
52         modification.delete();
53     }
54
55     /**
56      * Read a particular child. If the child has been modified and does not have a stable
57      * view, one will we instantiated with specified version.
58      */
59     Optional<NormalizedNode> read(final PathArgument child, final Version version) {
60         final ModifiedNode childNode = modification.childByArg(child);
61         if (childNode != null) {
62             var snapshot = childNode.getSnapshot();
63             if (snapshot == null) {
64                 // Snapshot is not present, force instantiation
65                 snapshot = Optional.ofNullable(
66                     applyOperation.getChildByArg(child).apply(childNode, childNode.original(), version));
67             }
68
69             return snapshot.map(TreeNode::getData);
70         }
71
72         var snapshot = modification.getSnapshot();
73         if (snapshot == null) {
74             snapshot = Optional.ofNullable(apply(modification.original(), version));
75         }
76
77         if (snapshot.isPresent()) {
78             return snapshot.orElseThrow().findChildByArg(child).map(TreeNode::getData);
79         }
80
81         return Optional.empty();
82     }
83
84     public ModifiedNode getModification() {
85         return modification;
86     }
87
88     public ModificationApplyOperation getApplyOperation() {
89         return applyOperation;
90     }
91
92     public @Nullable TreeNode apply(final @Nullable TreeNode data, final Version version) {
93         return applyOperation.apply(modification, data, version);
94     }
95
96     public static OperationWithModification from(final ModificationApplyOperation operation,
97             final ModifiedNode modification) {
98         return new OperationWithModification(operation, modification);
99     }
100 }