2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.xpath.api;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.base.MoreObjects.ToStringHelper;
15 import com.google.common.collect.ImmutableList;
16 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
17 import java.io.Serializable;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.Objects;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.common.QNameModule;
28 public class YangLocationPath implements YangExpr {
29 public abstract static class Step implements Serializable, YangPredicateAware {
30 private static final long serialVersionUID = 1L;
32 private final YangXPathAxis axis;
34 Step(final YangXPathAxis axis) {
35 this.axis = requireNonNull(axis);
38 public final YangXPathAxis getAxis() {
43 public abstract int hashCode();
46 public abstract boolean equals(@Nullable Object obj);
49 public final String toString() {
50 return addToStringAttributes(MoreObjects.toStringHelper(Step.class)).toString();
53 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
54 helper.add("axis", axis);
55 final Set<YangExpr> predicates = getPredicates();
56 if (!predicates.isEmpty()) {
57 helper.add("predicates", predicates);
63 public static class AxisStep extends Step {
64 private static final long serialVersionUID = 1L;
66 AxisStep(final YangXPathAxis axis) {
71 public final int hashCode() {
72 return Objects.hash(getAxis(), getPredicates());
76 public final boolean equals(@Nullable final Object obj) {
80 if (!(obj instanceof AxisStep)) {
83 final AxisStep other = (AxisStep) obj;
84 return getAxis().equals(other.getAxis()) && getPredicates().equals(other.getPredicates());
87 @SuppressFBWarnings(value = "SE_PRIVATE_READ_RESOLVE_NOT_INHERITED",
88 justification = "We have only one subclass, and that does not want to inherit this")
89 private Object readResolve() {
90 return getAxis().asStep();
94 static final class AxisStepWithPredicates extends AxisStep {
95 private static final long serialVersionUID = 1L;
97 private final Set<YangExpr> predicates;
99 AxisStepWithPredicates(final YangXPathAxis axis, final Set<YangExpr> predicates) {
101 this.predicates = requireNonNull(predicates);
105 public Set<YangExpr> getPredicates() {
110 // match a particular namespace
111 public static class NamespaceStep extends Step {
112 private static final long serialVersionUID = 1L;
114 private final QNameModule namespace;
116 NamespaceStep(final YangXPathAxis axis, final QNameModule namespace) {
118 this.namespace = requireNonNull(namespace);
121 public final QNameModule getNamespace() {
126 public final int hashCode() {
127 return Objects.hash(getAxis(), namespace, getPredicates());
131 public final boolean equals(@Nullable final Object obj) {
135 if (!(obj instanceof NamespaceStep)) {
138 final NamespaceStep other = (NamespaceStep) obj;
139 return getAxis().equals(other.getAxis()) && namespace.equals(other.namespace)
140 && getPredicates().equals(other.getPredicates());
144 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
145 return super.addToStringAttributes(helper).add("namespace", namespace);
149 public static class QNameStep extends Step {
150 private static final long serialVersionUID = 1L;
152 private final QName qname;
154 QNameStep(final YangXPathAxis axis, final QName qname) {
156 this.qname = requireNonNull(qname);
159 public final QName getQName() {
164 public final int hashCode() {
165 return Objects.hash(getAxis(), qname, getPredicates());
169 public final boolean equals(@Nullable final Object obj) {
173 if (!(obj instanceof QNameStep)) {
176 final QNameStep other = (QNameStep) obj;
177 return getAxis().equals(other.getAxis()) && qname.equals(other.qname)
178 && getPredicates().equals(other.getPredicates());
182 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
183 return super.addToStringAttributes(helper).add("qname", qname);
187 static final class QNameStepWithPredicates extends QNameStep {
188 private static final long serialVersionUID = 1L;
190 private final Set<YangExpr> predicates;
192 QNameStepWithPredicates(final YangXPathAxis axis, final QName qname, final Set<YangExpr> predicates) {
194 this.predicates = requireNonNull(predicates);
198 public Set<YangExpr> getPredicates() {
203 public static class NodeTypeStep extends Step {
204 private static final long serialVersionUID = 1L;
206 private final YangXPathNodeType nodeType;
208 NodeTypeStep(final YangXPathAxis axis, final YangXPathNodeType nodeType) {
210 this.nodeType = requireNonNull(nodeType);
213 public final YangXPathNodeType getNodeType() {
218 public int hashCode() {
219 return Objects.hash(getAxis(), nodeType, getPredicates());
223 public boolean equals(@Nullable final Object obj) {
227 if (obj == null || !getClass().equals(obj.getClass())) {
230 final NodeTypeStep other = (NodeTypeStep) obj;
231 return nodeType.equals(other.nodeType) && getAxis().equals(other.getAxis())
232 && getPredicates().equals(other.getPredicates());
236 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
237 return super.addToStringAttributes(helper).add("nodeType", nodeType);
241 @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS",
242 justification = "https://github.com/spotbugs/spotbugs/issues/511")
243 static final class NodeTypeStepWithPredicates extends NodeTypeStep {
244 private static final long serialVersionUID = 1L;
246 private final Set<YangExpr> predicates;
248 NodeTypeStepWithPredicates(final YangXPathAxis axis, final YangXPathNodeType type,
249 final Set<YangExpr> predicates) {
251 this.predicates = requireNonNull(predicates);
255 public Set<YangExpr> getPredicates() {
260 public static class ProcessingInstructionStep extends NodeTypeStep {
261 private static final long serialVersionUID = 1L;
263 private final String name;
265 ProcessingInstructionStep(final YangXPathAxis axis, final String name) {
266 super(axis, YangXPathNodeType.PROCESSING_INSTRUCTION);
267 this.name = requireNonNull(name);
270 public final String getName() {
275 public final int hashCode() {
276 return Objects.hash(getAxis(), getNodeType(), name, getPredicates());
280 public final boolean equals(final @Nullable Object obj) {
281 return obj == this || super.equals(obj) && name.equals(((ProcessingInstructionStep) obj).name);
285 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
286 return super.addToStringAttributes(helper).add("name", name);
290 static final class ProcessingInstructionStepWithPredicates extends ProcessingInstructionStep {
291 private static final long serialVersionUID = 1L;
293 private final Set<YangExpr> predicates;
295 ProcessingInstructionStepWithPredicates(final YangXPathAxis axis, final String name,
296 final Set<YangExpr> predicates) {
298 this.predicates = requireNonNull(predicates);
302 public Set<YangExpr> getPredicates() {
307 public static class Absolute extends YangLocationPath {
308 private static final long serialVersionUID = 1L;
311 public final boolean isAbsolute() {
316 private static final class AbsoluteWithSteps extends Absolute {
317 private static final long serialVersionUID = 1L;
319 private final List<Step> steps;
321 AbsoluteWithSteps(final List<Step> steps) {
322 this.steps = requireNonNull(steps);
326 public List<Step> getSteps() {
331 private static final class WithSteps extends YangLocationPath {
332 private static final long serialVersionUID = 1L;
334 private final List<Step> steps;
336 WithSteps(final List<Step> steps) {
337 this.steps = requireNonNull(steps);
341 public List<Step> getSteps() {
346 private static final long serialVersionUID = 1L;
347 private static final YangLocationPath ROOT = new Absolute();
348 private static final YangLocationPath SELF = new YangLocationPath();
351 // Hidden to prevent external instantiation
354 public static final YangLocationPath of(final boolean absolute) {
355 return absolute ? ROOT : SELF;
358 public static final YangLocationPath of(final boolean absolute, final Step... steps) {
359 return of(absolute, Arrays.asList(steps));
362 public static final YangLocationPath of(final boolean absolute, final Collection<Step> steps) {
363 if (steps.isEmpty()) {
367 final List<Step> copy = ImmutableList.copyOf(steps);
368 return absolute ? new AbsoluteWithSteps(copy) : new WithSteps(copy);
372 * The conceptual {@code root} {@link YangLocationPath}. This path is an absolute path and has no steps.
374 * @return Empty absolute {@link YangLocationPath}
376 public static final YangLocationPath root() {
381 * The conceptual {@code same} {@link YangLocationPath}. This path is a relative path and has no steps and is
382 * equivalent to a step along {@link YangXPathAxis#SELF}.
384 * @return Empty relative {@link YangLocationPath}
386 public static YangLocationPath self() {
390 public boolean isAbsolute() {
394 public List<Step> getSteps() {
395 return ImmutableList.of();
399 public final int hashCode() {
400 return Boolean.hashCode(isAbsolute()) * 31 + getSteps().hashCode();
404 public final boolean equals(final @Nullable Object obj) {
408 if (!(obj instanceof YangLocationPath)) {
411 final YangLocationPath other = (YangLocationPath) obj;
412 return isAbsolute() == other.isAbsolute() && getSteps().equals(other.getSteps());
416 public final String toString() {
417 final ToStringHelper helper = MoreObjects.toStringHelper(YangLocationPath.class);
418 helper.add("absolute", isAbsolute());
419 final List<Step> steps = getSteps();
420 if (!steps.isEmpty()) {
421 helper.add("steps", steps);
423 return helper.toString();