840ceab47f680f63f4fc36ddaf3cc4140ea8f2d9
[yangtools.git] / yang / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / schema / tree / DataTreeCandidates.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.api.schema.tree;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import java.util.Iterator;
14 import javax.annotation.Nonnull;
15 import javax.annotation.Nullable;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
17 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * Utility class holding methods useful when dealing with {@link DataTreeCandidate} instances.
23  */
24 @Beta
25 public final class DataTreeCandidates {
26     private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidates.class);
27
28     private DataTreeCandidates() {
29         throw new UnsupportedOperationException();
30     }
31
32     public static DataTreeCandidate newDataTreeCandidate(final YangInstanceIdentifier rootPath,
33             final DataTreeCandidateNode rootNode) {
34         return new DefaultDataTreeCandidate(rootPath, rootNode);
35     }
36
37     public static DataTreeCandidate fromNormalizedNode(final YangInstanceIdentifier rootPath,
38             final NormalizedNode<?, ?> node) {
39         return new DefaultDataTreeCandidate(rootPath, new NormalizedNodeDataTreeCandidateNode(node));
40     }
41
42     public static void applyToCursor(final DataTreeModificationCursor cursor, final DataTreeCandidate candidate) {
43         DataTreeCandidateNodes.applyToCursor(cursor, candidate.getRootNode());
44     }
45
46     public static void applyToModification(final DataTreeModification modification,
47             final DataTreeCandidate candidate) {
48         if (modification instanceof CursorAwareDataTreeModification) {
49             applyToCursorAwareModification((CursorAwareDataTreeModification) modification, candidate);
50             return;
51         }
52
53         final DataTreeCandidateNode node = candidate.getRootNode();
54         final YangInstanceIdentifier path = candidate.getRootPath();
55         switch (node.getModificationType()) {
56             case DELETE:
57                 modification.delete(path);
58                 LOG.debug("Modification {} deleted path {}", modification, path);
59                 break;
60             case SUBTREE_MODIFIED:
61                 LOG.debug("Modification {} modified path {}", modification, path);
62
63                 NodeIterator iterator = new NodeIterator(null, path, node.getChildNodes().iterator());
64                 do {
65                     iterator = iterator.next(modification);
66                 } while (iterator != null);
67                 break;
68             case UNMODIFIED:
69                 LOG.debug("Modification {} unmodified path {}", modification, path);
70                 // No-op
71                 break;
72             case WRITE:
73                 modification.write(path, node.getDataAfter().get());
74                 LOG.debug("Modification {} written path {}", modification, path);
75                 break;
76             default:
77                 throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
78         }
79     }
80
81     private static void applyToCursorAwareModification(final CursorAwareDataTreeModification modification,
82             final DataTreeCandidate candidate) {
83         final YangInstanceIdentifier candidatePath = candidate.getRootPath();
84         if (candidatePath.isEmpty()) {
85             try (DataTreeModificationCursor cursor = modification.createCursor(candidatePath)) {
86                 DataTreeCandidateNodes.applyRootToCursor(cursor, candidate.getRootNode());
87             }
88         } else {
89             try (DataTreeModificationCursor cursor = modification.createCursor(candidatePath.getParent())) {
90                 DataTreeCandidateNodes.applyRootedNodeToCursor(cursor, candidatePath, candidate.getRootNode());
91             }
92         }
93     }
94
95     private static final class NodeIterator {
96         private final Iterator<DataTreeCandidateNode> iterator;
97         private final YangInstanceIdentifier path;
98         private final NodeIterator parent;
99
100         NodeIterator(@Nullable final NodeIterator parent, @Nonnull final YangInstanceIdentifier path,
101                 @Nonnull final Iterator<DataTreeCandidateNode> iterator) {
102             this.iterator = requireNonNull(iterator);
103             this.path = requireNonNull(path);
104             this.parent = parent;
105         }
106
107         NodeIterator next(final DataTreeModification modification) {
108             while (iterator.hasNext()) {
109                 final DataTreeCandidateNode node = iterator.next();
110                 final YangInstanceIdentifier child = path.node(node.getIdentifier());
111
112                 switch (node.getModificationType()) {
113                     case DELETE:
114                         modification.delete(child);
115                         LOG.debug("Modification {} deleted path {}", modification, child);
116                         break;
117                     case APPEARED:
118                     case DISAPPEARED:
119                     case SUBTREE_MODIFIED:
120                         LOG.debug("Modification {} modified path {}", modification, child);
121                         return new NodeIterator(this, child, node.getChildNodes().iterator());
122                     case UNMODIFIED:
123                         LOG.debug("Modification {} unmodified path {}", modification, child);
124                         // No-op
125                         break;
126                     case WRITE:
127                         modification.write(child, node.getDataAfter().get());
128                         LOG.debug("Modification {} written path {}", modification, child);
129                         break;
130                     default:
131                         throw new IllegalArgumentException("Unsupported modification " + node.getModificationType());
132                 }
133             }
134
135             return parent;
136         }
137     }
138 }