2 * Copyright (c) 2019 PANTHEON.tech, 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.model.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 org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.yangtools.concepts.Immutable;
18 import org.opendaylight.yangtools.yang.xpath.api.YangBinaryOperator;
19 import org.opendaylight.yangtools.yang.xpath.api.YangFunction;
20 import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath;
21 import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath.QNameStep;
22 import org.opendaylight.yangtools.yang.xpath.api.YangLocationPath.Relative;
23 import org.opendaylight.yangtools.yang.xpath.api.YangPathExpr;
24 import org.opendaylight.yangtools.yang.xpath.api.YangXPathAxis;
25 import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression;
28 * An expression as defined in <a href="https://tools.ietf.org/html/rfc7950#section-9.9.2">RFC7950 Section 9.9.2</a>,
29 * i.e. the argument of a {@code path} statement.
32 * Semantically a {@link PathExpression} is similar to a {@link YangXPathExpression} with guarantees around what
33 * subexpressions it can contain:
35 * <li>the root expression must be a {@link YangLocationPath}</li>
36 * <li>it can contain steps only along {@link YangXPathAxis#CHILD} and {@link YangXPathAxis#PARENT} axis</li>
37 * <li>all steps along {@link YangXPathAxis#CHILD} axis are {@link QNameStep}</li>
38 * <li>the only function invocation is {@link YangFunction#CURRENT}</li>
39 * <li>only {@link YangBinaryOperator#EQUALS} is allowed</li>
40 * <li>no literals nor numbers are allowed</li>
41 * <li>all qualified node identifiers must me resolved</li>
44 * @author Robert Varga
48 public interface PathExpression extends Immutable {
50 * Abstract base class for expressing steps of a PathExpression.
52 abstract class Steps {
54 // Prevent external subclassing
58 public abstract int hashCode();
61 public abstract boolean equals(@Nullable Object obj);
64 public final String toString() {
65 return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
68 abstract ToStringHelper addToStringAttributes(ToStringHelper helper);
72 * Steps of a PathExpression which is a LocationPath, corresponding to RFC7950 base specification.
74 final class LocationPathSteps extends Steps {
75 private final YangLocationPath locationPath;
77 public LocationPathSteps(final YangLocationPath locationPath) {
78 this.locationPath = requireNonNull(locationPath);
81 public YangLocationPath getLocationPath() {
86 public int hashCode() {
87 return locationPath.hashCode();
91 public boolean equals(final @Nullable Object obj) {
93 || obj instanceof LocationPathSteps && locationPath.equals(((LocationPathSteps) obj).locationPath);
97 ToStringHelper addToStringAttributes(final ToStringHelper helper) {
98 return helper.add("locationPath", locationPath);
103 * Steps of a PathExpression which is a combination of {@code deref()} function call and a relative path,
104 * corresponding to Errata 5617.
106 final class DerefSteps extends Steps {
107 private final Relative derefArgument;
108 private final Relative relativePath;
110 public DerefSteps(final Relative derefArgument, final Relative relativePath) {
111 this.derefArgument = requireNonNull(derefArgument);
112 this.relativePath = requireNonNull(relativePath);
115 public Relative getDerefArgument() {
116 return derefArgument;
119 public Relative getRelativePath() {
124 public int hashCode() {
125 return 31 * derefArgument.hashCode() + relativePath.hashCode();
129 public boolean equals(@Nullable final Object obj) {
133 if (!(obj instanceof DerefSteps)) {
136 final DerefSteps other = (DerefSteps) obj;
137 return derefArgument.equals(other.derefArgument) && relativePath.equals(other.relativePath);
141 ToStringHelper addToStringAttributes(final ToStringHelper helper) {
142 return helper.add("derefArgument", derefArgument).add("relativePath", relativePath);
147 * Returns the path expression formatted string as is defined in model. For example:
148 * {@code /prefix:container/prefix:container::cond[when()=foo]/prefix:leaf}
150 * @return the path expression formatted string as is defined in model.
152 String getOriginalString();
155 * Return the path of this expression, which can either be a {@link YangLocationPath} (compliant to RFC7950) or
156 * a {@link YangPathExpr} with filter being an invocation of {@link YangFunction#DEREF}.
158 * @return The path's steps
159 * @throws UnsupportedOperationException if the implementation has not parsed the string. Implementations are
160 * strongly encouraged to perform proper parsing.
165 * Returns <code>true</code> if the XPapth starts in root of YANG model, otherwise returns <code>false</code>.
167 * @return <code>true</code> if the XPapth starts in root of YANG model, otherwise returns <code>false</code>
169 default boolean isAbsolute() {
170 final Steps steps = getSteps();
171 return steps instanceof LocationPathSteps && ((LocationPathSteps) steps).getLocationPath().isAbsolute();