Move yang-common(-netty)
[yangtools.git] / common / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / QNameModule.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. 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.base.MoreObjects;
13 import com.google.common.collect.Interner;
14 import com.google.common.collect.Interners;
15 import java.io.DataInput;
16 import java.io.DataOutput;
17 import java.io.IOException;
18 import java.io.Serializable;
19 import java.util.Objects;
20 import java.util.Optional;
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.yangtools.concepts.Identifier;
24 import org.opendaylight.yangtools.concepts.Immutable;
25 import org.opendaylight.yangtools.concepts.WritableObject;
26
27 public final class QNameModule implements Comparable<QNameModule>, Immutable, Serializable, Identifier, WritableObject {
28     private static final Interner<QNameModule> INTERNER = Interners.newWeakInterner();
29     private static final long serialVersionUID = 3L;
30
31     private final @NonNull XMLNamespace namespace;
32     private final @Nullable Revision revision;
33
34     private transient int hash = 0;
35
36     private QNameModule(final XMLNamespace namespace, final @Nullable Revision revision) {
37         this.namespace = requireNonNull(namespace);
38         this.revision = revision;
39     }
40
41     /**
42      * Return an interned reference to a equivalent QNameModule.
43      *
44      * @return Interned reference, or this object if it was interned.
45      */
46     public @NonNull QNameModule intern() {
47         return INTERNER.intern(this);
48     }
49
50     /**
51      * Create a new QName module instance with specified namespace/revision.
52      *
53      * @param namespace Module namespace
54      * @param revision Module revision
55      * @return A new, potentially shared, QNameModule instance
56      * @throws NullPointerException if any argument is null
57      */
58     public static @NonNull QNameModule create(final XMLNamespace namespace, final Optional<Revision> revision) {
59         return new QNameModule(namespace, revision.orElse(null));
60     }
61
62     /**
63      * Create a new QName module instance with specified namespace and no revision.
64      *
65      * @param namespace Module namespace
66      * @return A new, potentially shared, QNameModule instance
67      * @throws NullPointerException if {@code namespace} is null
68      */
69     public static @NonNull QNameModule create(final XMLNamespace namespace) {
70         return new QNameModule(namespace, null);
71     }
72
73     /**
74      * Create a new QName module instance with specified namespace/revision.
75      *
76      * @param namespace Module namespace
77      * @param revision Module revision
78      * @return A new, potentially shared, QNameModule instance
79      * @throws NullPointerException if any argument is null
80      */
81     public static @NonNull QNameModule create(final XMLNamespace namespace, final @Nullable Revision revision) {
82         return new QNameModule(namespace, revision);
83     }
84
85     /**
86      * Read a QNameModule from a DataInput. The format is expected to match the output format
87      * of {@link #writeTo(DataOutput)}.
88      *
89      * @param in DataInput to read
90      * @return A QNameModule instance
91      * @throws IOException if I/O error occurs
92      */
93     public static @NonNull QNameModule readFrom(final DataInput in) throws IOException {
94         final String namespace = in.readUTF();
95         final String revision = in.readUTF();
96         return new QNameModule(XMLNamespace.of(namespace), revision.isEmpty() ? null : Revision.of(revision));
97     }
98
99     /**
100      * Returns the namespace of the module which is specified as argument of YANG Module {@code namespace} keyword.
101      *
102      * @return XMLNamespace of the namespace of the module
103      */
104     public @NonNull XMLNamespace getNamespace() {
105         return namespace;
106     }
107
108     /**
109      * Returns the revision date for the module.
110      *
111      * @return date of the module revision which is specified as argument of YANG Module {@code revision} keyword
112      */
113     public @NonNull Optional<Revision> getRevision() {
114         return Optional.ofNullable(revision);
115     }
116
117     @Override
118     @SuppressWarnings("checkstyle:parameterName")
119     public int compareTo(final QNameModule o) {
120         int cmp = namespace.compareTo(o.namespace);
121         if (cmp != 0) {
122             return cmp;
123         }
124         return Revision.compare(revision, o.revision);
125     }
126
127     /**
128      * Returns a QNameModule with the same namespace, but with no revision. If this QNameModule does not have
129      * a revision, this object is returned.
130      *
131      * @return a QNameModule with the same namespace, but with no revision.
132      */
133     public @NonNull QNameModule withoutRevision() {
134         return revision == null ? this : new QNameModule(namespace, null);
135     }
136
137     @Override
138     public void writeTo(final DataOutput out) throws IOException {
139         out.writeUTF(namespace.toString());
140         out.writeUTF(revision == null ? "" : revision.toString());
141     }
142
143     @Override
144     public int hashCode() {
145         if (hash == 0) {
146             hash = Objects.hash(namespace, revision);
147         }
148         return hash;
149     }
150
151     @Override
152     public boolean equals(final Object obj) {
153         if (this == obj) {
154             return true;
155         }
156         if (!(obj instanceof QNameModule)) {
157             return false;
158         }
159         final QNameModule other = (QNameModule) obj;
160         return Objects.equals(revision, other.revision) && namespace.equals(other.namespace);
161     }
162
163     @Override
164     public @NonNull String toString() {
165         return MoreObjects.toStringHelper(QNameModule.class).omitNullValues().add("ns", namespace)
166             .add("rev", revision).toString();
167     }
168
169     Object writeReplace() {
170         return new NSv1(this);
171     }
172 }