/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.data.api; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Verify.verify; import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import java.io.Serializable; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.concepts.Path; import org.opendaylight.yangtools.util.HashCodeBuilder; import org.opendaylight.yangtools.util.ImmutableOffsetMap; import org.opendaylight.yangtools.util.SharedSingletonMap; 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 particular node instance in the data tree. * *
* Java representation of YANG Built-in type instance-identifier
,
* 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.
*
*
* Constraints put in YANG specification on instance-identifier allowed it to be * effectively represented in Java and it's evaluation does not require * full-blown XPath processor. * *
*
0..1
in particular subtree in data tree.0..n
.leaf
node or
* leaf-list
node.augmentation
node.* This interface itself is used as common parent for actual * path arguments types and should not be implemented by user code. * *
* Path arguments SHOULD contain only minimum of information * required to uniquely identify node on particular subtree level. * *
* For actual path arguments types see: *
* This method may return null, if the corresponding schema node, does
* not have QName associated, such as in cases of augmentations.
*
* @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 abstract static class AbstractPathArgument implements PathArgument {
private static final long serialVersionUID = -4546547994250849340L;
private final QName nodeType;
private transient int hashValue;
private transient volatile boolean hashGuard = false;
protected AbstractPathArgument(final QName nodeType) {
this.nodeType = requireNonNull(nodeType);
}
@Override
public final QName getNodeType() {
return nodeType;
}
@Override
@SuppressWarnings("checkstyle:parameterName")
public int compareTo(@Nonnull final PathArgument o) {
return nodeType.compareTo(o.getNodeType());
}
protected int hashCodeImpl() {
return 31 + getNodeType().hashCode();
}
@Override
public final int hashCode() {
if (!hashGuard) {
hashValue = hashCodeImpl();
hashGuard = true;
}
return hashValue;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null || this.getClass() != obj.getClass()) {
return false;
}
return getNodeType().equals(((AbstractPathArgument)obj).getNodeType());
}
@Override
public String toString() {
return getNodeType().toString();
}
@Override
public String toRelativeString(final PathArgument previous) {
if (previous instanceof AbstractPathArgument) {
final QNameModule mod = previous.getNodeType().getModule();
if (getNodeType().getModule().equals(mod)) {
return getNodeType().getLocalName();
}
}
return getNodeType().toString();
}
}
/**
* Simple path argument identifying a {@link org.opendaylight.yangtools.yang.data.api.schema.ContainerNode} or
* {@link org.opendaylight.yangtools.yang.data.api.schema.LeafNode} leaf in particular subtree.
*/
public static final class NodeIdentifier extends AbstractPathArgument {
private static final long serialVersionUID = -2255888212390871347L;
private static final LoadingCache
* Augmentation is uniquely identified by set of all possible child nodes.
* This is possible
* to identify instance of augmentation,
* since RFC6020 states that augment
that augment
* statement must not add multiple nodes from same namespace
* / module to the target node.
*
* @see RFC6020
*/
public static final class AugmentationIdentifier implements PathArgument {
private static final long serialVersionUID = -8122335594681936939L;
private final ImmutableSet