2 * Copyright © 2020 FRINX s.r.o. All rights reserved.
3 * Copyright © 2021 PANTHEON.tech, s.r.o.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netconf.util;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.collect.Maps;
14 import java.util.Collection;
15 import java.util.LinkedHashMap;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.opendaylight.yangtools.concepts.Mutable;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 * Representation of the tree node with possible multiple child nodes. Child nodes are identified uniquely by path
26 final class PathNode implements Mutable {
27 private final PathArgument argument;
29 private Map<PathArgument, PathNode> children;
31 private PathNode(final PathArgument argument, final LinkedHashMap<PathArgument, PathNode> children) {
32 this.argument = requireNonNull(argument);
33 this.children = requireNonNull(children);
37 * Creation of tree node using a path argument.
39 * @param argument Path argument
41 PathNode(final PathArgument argument) {
42 this.argument = requireNonNull(argument);
43 this.children = Map.of();
49 * @return path argument
51 PathArgument element() {
56 * Return current child nodes.
58 * @return Current child nodes
60 Collection<PathNode> children() {
61 return children.values();
65 * Return {@code true} if this node has no child nodes.
67 * @return {@code true} if this node has no child nodes
70 return children.isEmpty();
74 * Create a copy of this node with specified immediate child nodes appended.
76 * @param childArguments Child arguments
77 * @return A copy of this {@link PathNode}
78 * @throws NullPointerException if {@code childArguments} is, or contains, {@code null}
80 PathNode copyWith(final Collection<PathArgument> childArguments) {
81 final LinkedHashMap<PathArgument, PathNode> copy = children instanceof LinkedHashMap
82 ? new LinkedHashMap<>(children) : Maps.newLinkedHashMapWithExpectedSize(childArguments.size());
83 for (PathArgument childArgument : childArguments) {
84 ensureChild(copy, childArgument);
86 return new PathNode(argument, copy);
90 * Ensure a node for specified argument exists.
92 * @param childArgument Child argument
93 * @return A child {@link PathNode}
94 * @throws NullPointerException if {@code childArgument} is null
96 PathNode ensureChild(final PathArgument childArgument) {
97 return ensureChild(mutableChildren(), childArgument);
100 private static PathNode ensureChild(final LinkedHashMap<PathArgument, PathNode> children,
101 final PathArgument childArgument) {
102 return children.computeIfAbsent(requireNonNull(childArgument), PathNode::new);
105 private LinkedHashMap<PathArgument, PathNode> mutableChildren() {
106 final Map<PathArgument, PathNode> local = children;
107 if (local instanceof LinkedHashMap) {
108 return (LinkedHashMap<PathArgument, PathNode>) local;
111 // TODO: LinkedHashMap is rather heavy, do we need to retain insertion order?
112 final LinkedHashMap<PathArgument, PathNode> ret = new LinkedHashMap<>(4);