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 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 QualifiedQName 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 QualifiedQName 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);
63 @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "Interning identity check")
64 public QualifiedQName intern() {
65 // Make sure to intern the string and check whether it refers to the same name as we are
66 final String name = getLocalName();
67 final String internedName = name.intern();
68 final QualifiedQName template = internedName == name ? this : new QualifiedQName(prefix.intern(), internedName);
69 return INTERNER.intern(template);
73 @SuppressWarnings("checkstyle:parameterName")
74 public int compareTo(final QualifiedQName o) {
75 return getLocalName().compareTo(o.getLocalName());
79 public void writeTo(final DataOutput out) throws IOException {
80 out.writeUTF(getLocalName());
84 public int hashCode() {
85 return getLocalName().hashCode();
89 public boolean equals(final @Nullable Object obj) {
90 return this == obj || obj instanceof QualifiedQName
91 && getLocalName().equals(((AbstractQName) obj).getLocalName());
95 public String toString() {
96 return MoreObjects.toStringHelper(this).add("localName", getLocalName()).toString();
100 Object writeReplace() {
101 return new QQNv1(this);