2 * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.data.api.schema.tree;
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Optional;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
21 class TerminalDataTreeCandidateNode implements DataTreeCandidateNode {
22 private ModificationType modificationType;
23 private final PathArgument identifier;
24 private final NormalizedNode before;
25 private NormalizedNode after;
26 private final HashMap<PathArgument, TerminalDataTreeCandidateNode> childNodes = new HashMap<>();
27 private TerminalDataTreeCandidateNode parentNode;
29 TerminalDataTreeCandidateNode(PathArgument identifier, NormalizedNode data,
30 TerminalDataTreeCandidateNode parentNode) {
31 this(identifier, data);
32 this.parentNode = requireNonNull(parentNode);
35 TerminalDataTreeCandidateNode(PathArgument identifier, NormalizedNode data) {
36 this(identifier, ModificationType.UNMODIFIED, data, data);
39 TerminalDataTreeCandidateNode(PathArgument identifier, ModificationType modificationType,
40 NormalizedNode before, NormalizedNode after) {
41 this.modificationType = modificationType;
42 this.identifier = identifier;
48 public PathArgument getIdentifier() {
53 public Collection<DataTreeCandidateNode> getChildNodes() {
54 return Collections.unmodifiableCollection(childNodes.values());
58 public Optional<DataTreeCandidateNode> getModifiedChild(
59 PathArgument childIdentifier) {
60 return Optional.ofNullable(childNodes.get(identifier));
64 public ModificationType getModificationType() {
65 return modificationType;
69 public Optional<NormalizedNode> getDataAfter() {
70 return Optional.ofNullable(after);
73 @NonNull Optional<NormalizedNode> getDataAfter(PathArgument id) {
74 return getNode(id).flatMap(TerminalDataTreeCandidateNode::getDataAfter);
78 public Optional<NormalizedNode> getDataBefore() {
79 return Optional.ofNullable(before);
82 @NonNull Optional<NormalizedNode> getDataBefore(PathArgument id) {
83 Optional<TerminalDataTreeCandidateNode> node = getNode(id);
84 if (node.isPresent()) {
85 return node.get().getDataBefore();
87 return Optional.empty();
90 void setAfter(NormalizedNode after) {
94 void addChildNode(TerminalDataTreeCandidateNode node) {
95 childNodes.put(node.getIdentifier(), node);
98 void setModification(PathArgument id, ModificationType modification) {
99 Optional<TerminalDataTreeCandidateNode> node = getNode(id);
100 if (node.isEmpty()) {
101 throw new IllegalArgumentException("No node with " + id + " id was found");
103 node.get().setModification(modification);
106 private void setModification(ModificationType modification) {
107 this.modificationType = modification;
110 ModificationType getModification(PathArgument id) {
111 Optional<TerminalDataTreeCandidateNode> node = getNode(id);
112 return (node.isEmpty() ? ModificationType.UNMODIFIED : node.get().getModificationType());
115 void deleteNode(PathArgument id) {
117 modificationType = ModificationType.UNMODIFIED;
120 Optional<TerminalDataTreeCandidateNode> node = getNode(id);
121 if (node.isEmpty()) {
122 throw new IllegalArgumentException("No node with " + id + " id was found");
124 node.get().parentNode.deleteChild(id);
127 private void deleteChild(PathArgument id) {
128 childNodes.remove(id);
131 @NonNull Optional<TerminalDataTreeCandidateNode> getNode(PathArgument id) {
133 return Optional.of(this);
135 if (childNodes.isEmpty()) {
136 return Optional.empty();
138 if (childNodes.containsKey(id)) {
139 return Optional.ofNullable(childNodes.get(id));
144 void setData(PathArgument id, NormalizedNode node) {
145 TerminalDataTreeCandidateNode terminalDataTreeCandidateNode = getNode(id).get();
146 terminalDataTreeCandidateNode.setAfter(node);
149 private @NonNull Optional<TerminalDataTreeCandidateNode> findNode(PathArgument id) {
150 Collection<HashMap<PathArgument, TerminalDataTreeCandidateNode>> nodes = new HashSet<>();
151 childNodes.forEach((childIdentifier, childNode) -> {
152 nodes.add(childNode.childNodes);
154 return findNode(nodes, id);
157 private @NonNull Optional<TerminalDataTreeCandidateNode> findNode(
158 Collection<HashMap<PathArgument, TerminalDataTreeCandidateNode>> nodes,
160 if (nodes.isEmpty()) {
161 return Optional.empty();
163 Collection<HashMap<PathArgument, TerminalDataTreeCandidateNode>> nextNodes = new HashSet<>();
164 for (HashMap<PathArgument, TerminalDataTreeCandidateNode> map : nodes) {
165 if (map.containsKey(id)) {
166 return Optional.ofNullable(map.get(id));
168 map.forEach((childIdentifier, childNode) -> {
169 nextNodes.add(childNode.childNodes);
172 return findNode(nextNodes, id);