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.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.opendaylight.yangtools.concepts.Immutable;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.QNameModule;
24 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
27 * Represents unique path to the every schema node inside the schema node identifier namespace. This concept is defined
28 * in <a href="https://tools.ietf.org/html/rfc7950#section-6.5">RFC7950</a>.
30 public abstract class SchemaNodeIdentifier implements Immutable {
32 * An absolute schema node identifier.
34 public static final class Absolute extends SchemaNodeIdentifier {
35 Absolute(final QName qname) {
39 Absolute(final Collection<QName> qnames) {
43 public static @NonNull Absolute of(final QName nodeIdentifier) {
44 return new Absolute(nodeIdentifier);
47 public static @NonNull Absolute of(final QName... nodeIdentifiers) {
48 return new Absolute(Arrays.asList(nodeIdentifiers));
51 public static @NonNull Absolute of(final Collection<QName> nodeIdentifiers) {
52 return new Absolute(ImmutableList.copyOf(nodeIdentifiers));
56 SchemaPath implicitSchemaPathParent() {
57 return SchemaPath.ROOT;
62 * A descendant schema node identifier.
64 public static final class Descendant extends SchemaNodeIdentifier {
65 Descendant(final QName qname) {
69 Descendant(final Collection<QName> qnames) {
73 public static @NonNull Descendant of(final QName nodeIdentifier) {
74 return new Descendant(nodeIdentifier);
77 public static @NonNull Descendant of(final QName... nodeIdentifiers) {
78 return new Descendant(Arrays.asList(nodeIdentifiers));
81 public static @NonNull Descendant of(final Collection<QName> nodeIdentifiers) {
82 return new Descendant(nodeIdentifiers);
86 SchemaPath implicitSchemaPathParent() {
87 return SchemaPath.SAME;
91 private static final AtomicReferenceFieldUpdater<SchemaNodeIdentifier, SchemaPath> SCHEMAPATH_UPDATER =
92 AtomicReferenceFieldUpdater.newUpdater(SchemaNodeIdentifier.class, SchemaPath.class, "schemaPath");
94 private final @NonNull Object qnames;
97 private volatile SchemaPath schemaPath;
99 private volatile int hash;
101 SchemaNodeIdentifier(final QName qname) {
102 this.qnames = requireNonNull(qname);
105 SchemaNodeIdentifier(final Collection<QName> qnames) {
106 final ImmutableList<QName> tmp = ImmutableList.copyOf(qnames);
107 checkArgument(!tmp.isEmpty());
108 this.qnames = tmp.size() == 1 ? tmp.get(0) : tmp;
111 public @NonNull List<QName> getNodeIdentifiers() {
112 return qnames instanceof QName ? ImmutableList.of((QName) qnames) : (ImmutableList<QName>) qnames;
116 * Create the {@link SchemaPath} equivalent of this identifier.
118 * @return SchemaPath equivalent.
120 public final @NonNull SchemaPath asSchemaPath() {
121 final SchemaPath ret = schemaPath;
122 return ret != null ? ret : loadSchemaPath();
125 private SchemaPath loadSchemaPath() {
126 final SchemaPath newPath = implicitSchemaPathParent().createChild(getNodeIdentifiers());
127 return SCHEMAPATH_UPDATER.compareAndSet(this, null, newPath) ? newPath : schemaPath;
130 abstract SchemaPath implicitSchemaPathParent();
133 public final int hashCode() {
135 return (local = hash) != 0 ? local : (hash = qnames.hashCode());
139 public final boolean equals(final Object obj) {
143 if (obj == null || getClass() != obj.getClass()) {
146 return qnames.equals(((SchemaNodeIdentifier) obj).qnames);
150 public final String toString() {
151 return MoreObjects.toStringHelper(this).add("qnames", toStringQNames()).toString();
154 private List<?> toStringQNames() {
155 final List<QName> ids = getNodeIdentifiers();
156 return ids.size() < 2 ? ids : simplifyQNames(ids);
159 private static List<?> simplifyQNames(final List<QName> qnames) {
160 final List<Object> ret = new ArrayList<>(qnames.size());
162 QNameModule prev = null;
163 for (QName qname : qnames) {
164 final QNameModule module = qname.getModule();
165 ret.add(module.equals(prev) ? qname.getLocalName() : qname);