Improve InMemoryDataTreeModification state management
[yangtools.git] / data / yang-data-tree-ri / src / main / java / org / opendaylight / yangtools / yang / data / tree / impl / AbstractDataTreeTip.java
1 /*
2  * Copyright (c) 2015 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 java.util.Optional;
11 import org.eclipse.jdt.annotation.NonNull;
12 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
13 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateTip;
14 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
15 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeTip;
16 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
17 import org.opendaylight.yangtools.yang.data.tree.impl.node.TreeNode;
18
19 abstract class AbstractDataTreeTip implements DataTreeTip {
20     /**
21      * Return the current root node of this tip.
22      *
23      * @return Current tip root node, may not be null.
24      */
25     protected abstract @NonNull TreeNode getTipRoot();
26
27     abstract @NonNull YangInstanceIdentifier getRootPath();
28
29     @Override
30     public final void validate(final DataTreeModification modification) throws DataValidationFailedException {
31         final var m = accessMod(modification, "validate");
32         m.getStrategy().checkApplicable(new ModificationPath(getRootPath()), m.getRootModification(),
33             Optional.of(getTipRoot()), m.getVersion());
34     }
35
36     @Override
37     public final DataTreeCandidateTip prepare(final DataTreeModification modification) {
38         final var m = accessMod(modification, "prepare");
39         final var root = m.getRootModification();
40
41         final var currentRoot = getTipRoot();
42         if (root.getOperation() == LogicalOperation.NONE) {
43             return new NoopDataTreeCandidate(YangInstanceIdentifier.of(), root, currentRoot);
44         }
45
46         final var newRoot = m.getStrategy().apply(m.getRootModification(), Optional.of(currentRoot), m.getVersion())
47             .orElseThrow(() -> new IllegalStateException("Apply strategy failed to produce root node for modification "
48                 + modification));
49         return new InMemoryDataTreeCandidate(YangInstanceIdentifier.of(), root, currentRoot, newRoot);
50     }
51
52     private static @NonNull InMemoryDataTreeModification accessMod(final DataTreeModification mod, final String op) {
53         if (mod instanceof InMemoryDataTreeModification inMemoryMod) {
54             if (inMemoryMod.isSealed()) {
55                 return inMemoryMod;
56             }
57             throw new IllegalArgumentException("Attempted to " + op + " unsealed modification " + inMemoryMod);
58         }
59         throw new IllegalArgumentException("Invalid modification " + mod.getClass());
60     }
61 }