2 * Copyright (c) 2015 Cisco Systems, Inc. and others. 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.stmt;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.collect.ImmutableList;
15 import java.util.Arrays;
16 import java.util.Collection;
17 import java.util.List;
18 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.yangtools.concepts.Immutable;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
25 * Represents unique path to the every schema node inside the schema node identifier namespace. This concept is defined
26 * in <a href="https://tools.ietf.org/html/rfc7950#section-6.5">RFC7950</a>.
28 public abstract class SchemaNodeIdentifier implements Immutable {
30 * An absolute schema node identifier.
32 public static final class Absolute extends SchemaNodeIdentifier {
33 Absolute(final QName qname) {
37 Absolute(final Collection<QName> qnames) {
41 public static Absolute of(final QName nodeIdentifier) {
42 return new Absolute(nodeIdentifier);
45 public static Absolute of(final QName... nodeIdentifiers) {
46 return new Absolute(Arrays.asList(nodeIdentifiers));
49 public static Absolute of(final Collection<QName> nodeIdentifiers) {
50 return new Absolute(ImmutableList.copyOf(nodeIdentifiers));
54 SchemaPath implicitSchemaPathParent() {
55 return SchemaPath.ROOT;
60 * A descendant schema node identifier.
62 public static final class Descendant extends SchemaNodeIdentifier {
63 Descendant(final QName qname) {
67 Descendant(final Collection<QName> qnames) {
71 public static Descendant of(final QName nodeIdentifier) {
72 return new Descendant(nodeIdentifier);
75 public static Descendant of(final QName... nodeIdentifiers) {
76 return new Descendant(Arrays.asList(nodeIdentifiers));
79 public static Descendant of(final Collection<QName> nodeIdentifiers) {
80 return new Descendant(nodeIdentifiers);
84 SchemaPath implicitSchemaPathParent() {
85 return SchemaPath.SAME;
89 private static final AtomicReferenceFieldUpdater<SchemaNodeIdentifier, SchemaPath> SCHEMAPATH_UPDATER =
90 AtomicReferenceFieldUpdater.newUpdater(SchemaNodeIdentifier.class, SchemaPath.class, "schemaPath");
92 private final @NonNull Object qnames;
95 private volatile SchemaPath schemaPath;
97 private volatile int hash;
99 SchemaNodeIdentifier(final QName qname) {
100 this.qnames = requireNonNull(qname);
103 SchemaNodeIdentifier(final Collection<QName> qnames) {
104 final ImmutableList<QName> tmp = ImmutableList.copyOf(qnames);
105 checkArgument(!tmp.isEmpty());
106 this.qnames = tmp.size() == 1 ? tmp.get(0) : tmp;
109 public @NonNull List<QName> getNodeIdentifiers() {
110 return qnames instanceof QName ? ImmutableList.of((QName) qnames) : (ImmutableList<QName>) qnames;
114 * Create the {@link SchemaPath} equivalent of this identifier.
116 * @return SchemaPath equivalent.
118 public final @NonNull SchemaPath asSchemaPath() {
119 final SchemaPath ret = schemaPath;
120 return ret != null ? ret : loadSchemaPath();
123 private SchemaPath loadSchemaPath() {
124 final SchemaPath newPath = implicitSchemaPathParent().createChild(getNodeIdentifiers());
125 return SCHEMAPATH_UPDATER.compareAndSet(this, null, newPath) ? newPath : schemaPath;
128 abstract SchemaPath implicitSchemaPathParent();
131 public final int hashCode() {
133 return (local = hash) != 0 ? local : (hash = qnames.hashCode());
137 public final boolean equals(final Object obj) {
141 if (obj == null || getClass() != obj.getClass()) {
144 return qnames.equals(((SchemaNodeIdentifier) obj).qnames);
148 public final String toString() {
149 return MoreObjects.toStringHelper(this).add("qnames", qnames).toString();