Merge branch 'master' of ../controller
[yangtools.git] / yang / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / QualifiedQName.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.common;
9
10 import static java.util.Objects.requireNonNull;
11
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;
23
24 /**
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)}.
28  */
29 @Beta
30 @NonNullByDefault
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();
34
35     private final String prefix;
36
37     private QualifiedQName(final String prefix, final String localName) {
38         super(localName);
39         this.prefix = requireNonNull(prefix);
40     }
41
42     public static QualifiedQName of(final String prefix, final String localName) {
43         return new QualifiedQName(checkLocalName(prefix), checkLocalName(localName));
44     }
45
46     /**
47      * Read an UnboundQName from a DataInput. The format is expected to match the output format of
48      * {@link #writeTo(DataOutput)}.
49      *
50      * @param in DataInput to read
51      * @return An UnboundQName instance
52      * @throws IOException if I/O error occurs
53      */
54     public static QualifiedQName readFrom(final DataInput in) throws IOException {
55         return of(in.readUTF(), in.readUTF());
56     }
57
58     public Optional<QName> bindTo(final YangNamespaceContext namespaceContext) {
59         return namespaceContext.findNamespaceForPrefix(prefix).map(this::bindTo);
60     }
61
62     private QName bindTo(final QNameModule namespace) {
63         return new QName(namespace, getLocalName());
64     }
65
66     @Override
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);
74     }
75
76     @Override
77     @SuppressWarnings("checkstyle:parameterName")
78     public int compareTo(final QualifiedQName o) {
79         return getLocalName().compareTo(o.getLocalName());
80     }
81
82     @Override
83     public void writeTo(final DataOutput out) throws IOException {
84         out.writeUTF(getLocalName());
85     }
86
87     @Override
88     public int hashCode() {
89         return getLocalName().hashCode();
90     }
91
92     @Override
93     public boolean equals(final @Nullable Object obj) {
94         return this == obj || obj instanceof QualifiedQName
95                 && getLocalName().equals(((AbstractQName) obj).getLocalName());
96     }
97
98     @Override
99     public String toString() {
100         return MoreObjects.toStringHelper(this).add("localName", getLocalName()).toString();
101     }
102
103     @Override
104     Object writeReplace() {
105         return new QQNv1(this);
106     }
107 }