2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.common;
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.collect.Interner;
15 import com.google.common.collect.Interners;
16 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
17 import java.io.DataInput;
18 import java.io.DataOutput;
19 import java.io.IOException;
20 import java.util.Optional;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
25 * An unresolved, qualified {@link QName}. It is guaranteed to hold a valid {@link #getLocalName()} bound to a namespace
26 * identified through a prefix string, but remains unresolved. A resolved {@link QName} can be obtained through
27 * {@link #bindTo(YangNamespaceContext)}.
31 public final class QualifiedQName extends AbstractQName implements Comparable<QualifiedQName> {
32 private static final long serialVersionUID = 1L;
33 private static final Interner<QualifiedQName> INTERNER = Interners.newWeakInterner();
35 private final String prefix;
37 private QualifiedQName(final String prefix, final String localName) {
39 this.prefix = requireNonNull(prefix);
42 public static QualifiedQName of(final String prefix, final String localName) {
43 return new QualifiedQName(checkLocalName(prefix), checkLocalName(localName));
47 * Read an UnboundQName from a DataInput. The format is expected to match the output format of
48 * {@link #writeTo(DataOutput)}.
50 * @param in DataInput to read
51 * @return An UnboundQName instance
52 * @throws IOException if I/O error occurs
54 public static QualifiedQName readFrom(final DataInput in) throws IOException {
55 return of(in.readUTF(), in.readUTF());
58 public Optional<QName> bindTo(final YangNamespaceContext namespaceContext) {
59 return namespaceContext.findNamespaceForPrefix(prefix).map(this::bindTo);
62 private QName bindTo(final QNameModule namespace) {
63 return new QName(namespace, getLocalName());
67 @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "Interning identity check")
68 public QualifiedQName intern() {
69 // Make sure to intern the string and check whether it refers to the same name as we are
70 final String name = getLocalName();
71 final String internedName = name.intern();
72 final QualifiedQName template = internedName == name ? this : new QualifiedQName(prefix.intern(), internedName);
73 return INTERNER.intern(template);
77 @SuppressWarnings("checkstyle:parameterName")
78 public int compareTo(final QualifiedQName o) {
79 return getLocalName().compareTo(o.getLocalName());
83 public void writeTo(final DataOutput out) throws IOException {
84 out.writeUTF(getLocalName());
88 public int hashCode() {
89 return getLocalName().hashCode();
93 public boolean equals(final @Nullable Object obj) {
94 return this == obj || obj instanceof QualifiedQName
95 && getLocalName().equals(((AbstractQName) obj).getLocalName());
99 public String toString() {
100 return MoreObjects.toStringHelper(this).add("localName", getLocalName()).toString();
104 Object writeReplace() {
105 return new QQNv1(this);