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 java.io.Serializable;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.List;
20 import java.util.Objects;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.QNameModule;
27 public class YangLocationPath implements YangExpr {
28 public abstract static class Step implements Serializable, YangPredicateAware {
29 private static final long serialVersionUID = 1L;
31 private final YangXPathAxis axis;
33 Step(final YangXPathAxis axis) {
34 this.axis = requireNonNull(axis);
37 public final YangXPathAxis getAxis() {
42 public abstract int hashCode();
45 public abstract boolean equals(@Nullable Object obj);
48 public final String toString() {
49 return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
52 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
53 helper.add("axis", axis);
54 final Set<YangExpr> predicates = getPredicates();
55 if (!predicates.isEmpty()) {
56 helper.add("predicates", predicates);
62 public static class AxisStep extends Step {
63 private static final long serialVersionUID = 1L;
65 AxisStep(final YangXPathAxis axis) {
70 public final int hashCode() {
71 return Objects.hash(getAxis(), getPredicates());
75 public final boolean equals(@Nullable final Object obj) {
79 if (!(obj instanceof AxisStep)) {
82 final AxisStep other = (AxisStep) obj;
83 return getAxis().equals(other.getAxis()) && getPredicates().equals(other.getPredicates());
86 private Object readResolve() {
87 return getAxis().asStep();
91 static final class AxisStepWithPredicates extends AxisStep {
92 private static final long serialVersionUID = 1L;
94 private final Set<YangExpr> predicates;
96 AxisStepWithPredicates(final YangXPathAxis axis, final Set<YangExpr> predicates) {
98 this.predicates = requireNonNull(predicates);
102 public Set<YangExpr> getPredicates() {
107 // match a particular namespace
108 public static class NamespaceStep extends Step {
109 private static final long serialVersionUID = 1L;
111 private final QNameModule namespace;
113 NamespaceStep(final YangXPathAxis axis, final QNameModule namespace) {
115 this.namespace = requireNonNull(namespace);
118 public final QNameModule getNamespace() {
123 public final int hashCode() {
124 return Objects.hash(getAxis(), namespace, getPredicates());
128 public final boolean equals(@Nullable final Object obj) {
132 if (!(obj instanceof NamespaceStep)) {
135 final NamespaceStep other = (NamespaceStep) obj;
136 return getAxis().equals(other.getAxis()) && namespace.equals(other.namespace)
137 && getPredicates().equals(other.getPredicates());
141 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
142 return super.addToStringAttributes(helper).add("namespace", namespace);
146 public static class QNameStep extends Step {
147 private static final long serialVersionUID = 1L;
149 private final QName qname;
151 QNameStep(final YangXPathAxis axis, final QName qname) {
153 this.qname = requireNonNull(qname);
156 public final QName getQName() {
161 public final int hashCode() {
162 return Objects.hash(getAxis(), qname, getPredicates());
166 public final boolean equals(@Nullable final Object obj) {
170 if (!(obj instanceof QNameStep)) {
173 final QNameStep other = (QNameStep) obj;
174 return getAxis().equals(other.getAxis()) && qname.equals(other.qname)
175 && getPredicates().equals(other.getPredicates());
179 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
180 return super.addToStringAttributes(helper).add("qname", qname);
184 static final class QNameStepWithPredicates extends QNameStep {
185 private static final long serialVersionUID = 1L;
187 private final Set<YangExpr> predicates;
189 QNameStepWithPredicates(final YangXPathAxis axis, final QName qname, final Set<YangExpr> predicates) {
191 this.predicates = requireNonNull(predicates);
195 public Set<YangExpr> getPredicates() {
200 public static class NodeTypeStep extends Step {
201 private static final long serialVersionUID = 1L;
203 private final YangXPathNodeType nodeType;
205 NodeTypeStep(final YangXPathAxis axis, final YangXPathNodeType nodeType) {
207 this.nodeType = requireNonNull(nodeType);
210 public final YangXPathNodeType getNodeType() {
215 public int hashCode() {
216 return Objects.hash(getAxis(), nodeType, getPredicates());
220 public boolean equals(@Nullable final Object obj) {
224 if (obj == null || !getClass().equals(obj.getClass())) {
227 final NodeTypeStep other = (NodeTypeStep) obj;
228 return nodeType.equals(other.nodeType) && getAxis().equals(other.getAxis())
229 && getPredicates().equals(other.getPredicates());
233 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
234 return super.addToStringAttributes(helper).add("nodeType", nodeType);
238 static final class NodeTypeStepWithPredicates extends NodeTypeStep {
239 private static final long serialVersionUID = 1L;
241 private final Set<YangExpr> predicates;
243 NodeTypeStepWithPredicates(final YangXPathAxis axis, final YangXPathNodeType type,
244 final Set<YangExpr> predicates) {
246 this.predicates = requireNonNull(predicates);
250 public Set<YangExpr> getPredicates() {
255 public static class ProcessingInstructionStep extends NodeTypeStep {
256 private static final long serialVersionUID = 1L;
258 private final String name;
260 ProcessingInstructionStep(final YangXPathAxis axis, final String name) {
261 super(axis, YangXPathNodeType.PROCESSING_INSTRUCTION);
262 this.name = requireNonNull(name);
265 public final String getName() {
270 public final int hashCode() {
271 return Objects.hash(getAxis(), getNodeType(), name, getPredicates());
275 public final boolean equals(final @Nullable Object obj) {
276 return obj == this || super.equals(obj) && name.equals(((ProcessingInstructionStep) obj).name);
280 protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
281 return super.addToStringAttributes(helper).add("name", name);
285 static final class ProcessingInstructionStepWithPredicates extends ProcessingInstructionStep {
286 private static final long serialVersionUID = 1L;
288 private final Set<YangExpr> predicates;
290 ProcessingInstructionStepWithPredicates(final YangXPathAxis axis, final String name,
291 final Set<YangExpr> predicates) {
293 this.predicates = requireNonNull(predicates);
297 public Set<YangExpr> getPredicates() {
302 public static class Absolute extends YangLocationPath {
303 private static final long serialVersionUID = 1L;
306 public final boolean isAbsolute() {
311 private static final class AbsoluteWithSteps extends Absolute {
312 private static final long serialVersionUID = 1L;
314 private final List<Step> steps;
316 AbsoluteWithSteps(final List<Step> steps) {
317 this.steps = requireNonNull(steps);
321 public List<Step> getSteps() {
326 private static final class WithSteps extends YangLocationPath {
327 private static final long serialVersionUID = 1L;
329 private final List<Step> steps;
331 WithSteps(final List<Step> steps) {
332 this.steps = requireNonNull(steps);
336 public List<Step> getSteps() {
341 private static final long serialVersionUID = 1L;
342 private static final YangLocationPath ROOT = new Absolute();
343 private static final YangLocationPath SELF = new YangLocationPath();
346 // Hidden to prevent external instantiation
349 public static final YangLocationPath of(final boolean absolute) {
350 return absolute ? ROOT : SELF;
353 public static final YangLocationPath of(final boolean absolute, final Step... steps) {
354 return of(absolute, Arrays.asList(steps));
357 public static final YangLocationPath of(final boolean absolute, final Collection<Step> steps) {
358 if (steps.isEmpty()) {
362 final List<Step> copy = ImmutableList.copyOf(steps);
363 return absolute ? new AbsoluteWithSteps(copy) : new WithSteps(copy);
367 * The conceptual {@code root} {@link YangLocationPath}. This path is an absolute path and has no steps.
369 * @return Empty absolute {@link YangLocationPath}
371 public static final YangLocationPath root() {
376 * The conceptual {@code same} {@link YangLocationPath}. This path is a relative path and has no steps and is
377 * equivalent to a step along {@link YangXPathAxis#SELF}.
379 * @return Empty relative {@link YangLocationPath}
381 public static YangLocationPath self() {
385 public boolean isAbsolute() {
389 public List<Step> getSteps() {
390 return ImmutableList.of();
394 public final int hashCode() {
395 return Boolean.hashCode(isAbsolute()) * 31 + getSteps().hashCode();
399 public final boolean equals(final @Nullable Object obj) {
403 if (!(obj instanceof YangLocationPath)) {
406 final YangLocationPath other = (YangLocationPath) obj;
407 return isAbsolute() == other.isAbsolute() && getSteps().equals(other.getSteps());