Refactor ModificationApplyOperation
[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             Optional<? extends TreeNode> snapshot = childNode.getSnapshot();
63             if (snapshot == null) {
64                 // Snapshot is not present, force instantiation
65                 snapshot = applyOperation.getChildByArg(child).apply(childNode, childNode.original(), version);
66             }
67
68             return snapshot.map(TreeNode::getData);
69         }
70
71         Optional<? extends TreeNode> snapshot = modification.getSnapshot();
72         if (snapshot == null) {
73             snapshot = apply(modification.original(), version);
74         }
75
76         if (snapshot.isPresent()) {
77             return snapshot.orElseThrow().findChildByArg(child).map(TreeNode::getData);
78         }
79
80         return Optional.empty();
81     }
82
83     public ModifiedNode getModification() {
84         return modification;
85     }
86
87     public ModificationApplyOperation getApplyOperation() {
88         return applyOperation;
89     }
90
91     public Optional<? extends TreeNode> apply(final @Nullable TreeNode data, final Version version) {
92         return applyOperation.apply(modification, data, version);
93     }
94
95     public static OperationWithModification from(final ModificationApplyOperation operation,
96             final ModifiedNode modification) {
97         return new OperationWithModification(operation, modification);
98     }
99 }