NormalizedMetadata is not Identifiable
[yangtools.git] / data / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / StackedYangInstanceIdentifier.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;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Verify.verify;
12 import static com.google.common.base.Verify.verifyNotNull;
13 import static java.util.Objects.requireNonNull;
14
15 import com.google.common.collect.Iterables;
16 import com.google.common.collect.Lists;
17 import java.io.Serial;
18 import java.util.ArrayList;
19 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.opendaylight.yangtools.util.HashCodeBuilder;
22
23 final class StackedYangInstanceIdentifier extends YangInstanceIdentifier implements Cloneable {
24     @Serial
25     private static final long serialVersionUID = 1L;
26
27     private final @NonNull YangInstanceIdentifier parent;
28     private final @NonNull PathArgument pathArgument;
29
30     private transient volatile StackedPathArguments pathArguments;
31     private transient volatile StackedReversePathArguments reversePathArguments;
32
33     StackedYangInstanceIdentifier(final YangInstanceIdentifier parent, final PathArgument pathArgument) {
34         this.parent = requireNonNull(parent);
35         this.pathArgument = requireNonNull(pathArgument);
36     }
37
38     @Override
39     public StackedYangInstanceIdentifier clone() {
40         try {
41             return (StackedYangInstanceIdentifier) super.clone();
42         } catch (CloneNotSupportedException e) {
43             throw new IllegalStateException("clone() should be supported", e);
44         }
45     }
46
47     @Override
48     public @NonNull YangInstanceIdentifier getParent() {
49         return parent;
50     }
51
52     @Override
53     public YangInstanceIdentifier coerceParent() {
54         return parent;
55     }
56
57     @Override
58     public YangInstanceIdentifier getAncestor(final int depth) {
59         checkArgument(depth >= 0, "Steps cannot be negative");
60
61         // Calculate how far up our FixedYangInstanceIdentifier ancestor is
62         int stackedDepth = 1;
63         YangInstanceIdentifier wlk = getParent();
64         while (wlk instanceof StackedYangInstanceIdentifier) {
65             wlk = wlk.getParent();
66             stackedDepth++;
67         }
68
69         // Guaranteed to come from FixedYangInstanceIdentifier
70         final int fixedDepth = wlk.getPathArguments().size();
71         if (fixedDepth >= depth) {
72             return wlk.getAncestor(depth);
73         }
74
75         // Calculate our depth and check argument
76         final int ourDepth = stackedDepth + fixedDepth;
77         checkArgument(depth <= ourDepth, "Depth %s exceeds maximum depth %s", depth, ourDepth);
78
79         // Requested depth is covered by the stack, traverse up for specified number of steps
80         final int toWalk = ourDepth - depth;
81         YangInstanceIdentifier result = this;
82         for (int i = 0; i < toWalk; ++i) {
83             result = verifyNotNull(result.getParent());
84         }
85
86         return result;
87     }
88
89     @Override
90     public boolean isEmpty() {
91         return false;
92     }
93
94     @Override
95     public List<PathArgument> getPathArguments() {
96         StackedPathArguments ret = tryPathArguments();
97         if (ret == null) {
98             final List<PathArgument> stack = new ArrayList<>();
99             YangInstanceIdentifier current = this;
100             do {
101                 verify(current instanceof StackedYangInstanceIdentifier);
102                 final StackedYangInstanceIdentifier stacked = (StackedYangInstanceIdentifier) current;
103                 stack.add(stacked.getLastPathArgument());
104                 current = stacked.getParent();
105             } while (current.tryPathArguments() == null);
106
107             pathArguments = ret = new StackedPathArguments(current, Lists.reverse(stack));
108         }
109
110         return ret;
111     }
112
113     @Override
114     public List<PathArgument> getReversePathArguments() {
115         StackedReversePathArguments ret = tryReversePathArguments();
116         if (ret == null) {
117             ret = new StackedReversePathArguments(this);
118             reversePathArguments = ret;
119         }
120         return ret;
121     }
122
123     @Override
124     public PathArgument getLastPathArgument() {
125         return pathArgument;
126     }
127
128     @Override
129     StackedPathArguments tryPathArguments() {
130         return pathArguments;
131     }
132
133     @Override
134     StackedReversePathArguments tryReversePathArguments() {
135         return reversePathArguments;
136     }
137
138     @Override
139     YangInstanceIdentifier createRelativeIdentifier(final int skipFromRoot) {
140         // TODO: can we optimize this one?
141         return YangInstanceIdentifier.create(Iterables.skip(getPathArguments(), skipFromRoot));
142     }
143
144     @Override
145     int computeHashCode() {
146         return HashCodeBuilder.nextHashCode(parent.hashCode(), pathArgument);
147     }
148
149     @Override
150     boolean pathArgumentsEqual(final YangInstanceIdentifier other) {
151         if (other instanceof StackedYangInstanceIdentifier stacked) {
152             return pathArgument.equals(stacked.pathArgument) && parent.equals(stacked.parent);
153         }
154         return super.pathArgumentsEqual(other);
155     }
156
157     @Override
158     public YangInstanceIdentifier toOptimized() {
159         return FixedYangInstanceIdentifier.create(getPathArguments());
160     }
161 }