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