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