import org.opendaylight.yangtools.concepts.Path;
import org.opendaylight.yangtools.util.HashCodeBuilder;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
/**
- * Unique identifier of a partical node instance in the data tree.
+ * Unique identifier of a particular node instance in the data tree.
*
* <p>
* Java representation of YANG Built-in type <code>instance-identifier</code>,
- * which conceptually is XPath expression minimised to uniquely identify element
+ * which conceptually is XPath expression minimized to uniquely identify element
* in data tree which conforms to constraints maintained by YANG Model,
* effectively this makes Instance Identifier a path to element in data tree.
* <p>
private final Iterable<PathArgument> pathArguments;
private final int hash;
- private transient ImmutableList<PathArgument> legacyPath = null;
- private transient String toStringCache = null;
+ private transient volatile ImmutableList<PathArgument> legacyPath = null;
+ private transient volatile String toStringCache = null;
private final ImmutableList<PathArgument> getLegacyPath() {
- if (legacyPath == null) {
+ // Temporary variable saves a volatile read
+ ImmutableList<PathArgument> ret = legacyPath;
+ if (ret == null) {
synchronized (this) {
- if (legacyPath == null) {
- legacyPath = ImmutableList.copyOf(pathArguments);
- }
+ // We could have used a synchronized block, but let's just not bother
+ ret = ImmutableList.copyOf(pathArguments);
+ legacyPath = ret;
}
}
- return legacyPath;
+ return ret;
}
/**
/**
* Path argument / component of InstanceIdentifier
*
- * Path argument uniquelly identifies node in data tree on particular
+ * Path argument uniquely identifies node in data tree on particular
* level.
* <p>
* This interface itself is used as common parent for actual
* @return Node type
*/
QName getNodeType();
+
+ /**
+ * Return the string representation of this object for use in context
+ * provided by a previous object. This method can be implemented in
+ * terms of {@link #toString()}, but implementations are encourage to
+ * reuse any context already emitted by the previous object.
+ *
+ * @param previous Previous path argument
+ * @return String representation
+ */
+ String toRelativeString(PathArgument previous);
}
private static abstract class AbstractPathArgument implements PathArgument {
public String toString() {
return getNodeType().toString();
}
+
+ @Override
+ public String toRelativeString(final PathArgument previous) {
+ if (previous instanceof AbstractPathArgument) {
+ final QNameModule mod = ((AbstractPathArgument)previous).getNodeType().getModule();
+ if (getNodeType().getModule().equals(mod)) {
+ return getNodeType().getLocalName();
+ }
+ }
+
+ return getNodeType().toString();
+ }
}
/**
public String toString() {
return super.toString() + '[' + keyValues + ']';
}
+
+ @Override
+ public String toRelativeString(final PathArgument previous) {
+ return super.toRelativeString(previous) + '[' + keyValues + ']';
+ }
}
/**
public String toString() {
return super.toString() + '[' + value + ']';
}
+
+ @Override
+ public String toRelativeString(final PathArgument previous) {
+ return super.toRelativeString(previous) + '[' + value + ']';
+ }
}
/**
}
/**
- *
* Returns set of all possible child nodes
*
* @return set of all possible child nodes.
return sb.toString();
}
+ @Override
+ public String toRelativeString(final PathArgument previous) {
+ return toString();
+ }
+
@Override
public boolean equals(final Object o) {
if (this == o) {
* The cache is thread-safe - if multiple computations occurs at the
* same time, cache will be overwritten with same result.
*/
- if (toStringCache != null) {
- return toStringCache;
- }
+ String ret = toStringCache;
+ if (ret == null) {
+ synchronized (this) {
+ ret = toStringCache;
+ if (ret == null) {
+ final StringBuilder builder = new StringBuilder("/");
+ PathArgument prev = null;
+ for (PathArgument argument : getPathArguments()) {
+ if (prev != null) {
+ builder.append('/');
+ }
+ builder.append(argument.toRelativeString(prev));
+ prev = argument;
+ }
- final StringBuilder builder = new StringBuilder('/');
- boolean first = true;
- for (PathArgument argument : getPathArguments()) {
- if (first) {
- first = false;
- } else {
- builder.append('/');
+ ret = builder.toString();
+ toStringCache = ret;
+ }
}
- builder.append(argument.toString());
}
-
- toStringCache = builder.toString();
- return toStringCache;
+ return ret;
}
}