2 * Copyright (c) 2013 Cisco Systems, Inc. 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.base.MoreObjects;
13 import com.google.common.collect.Interner;
14 import com.google.common.collect.Interners;
15 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
16 import java.io.DataInput;
17 import java.io.DataOutput;
18 import java.io.IOException;
19 import java.io.Serializable;
21 import java.net.URISyntaxException;
22 import java.util.Objects;
23 import java.util.Optional;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.opendaylight.yangtools.concepts.Identifier;
27 import org.opendaylight.yangtools.concepts.Immutable;
28 import org.opendaylight.yangtools.concepts.WritableObject;
31 public final class QNameModule implements Comparable<QNameModule>, Immutable, Serializable, Identifier, WritableObject {
32 private static final Interner<QNameModule> INTERNER = Interners.newWeakInterner();
33 private static final long serialVersionUID = 3L;
35 private final URI namespace;
36 private final @Nullable Revision revision;
38 private transient int hash = 0;
40 private QNameModule(final URI namespace, final @Nullable Revision revision) {
41 this.namespace = requireNonNull(namespace);
42 this.revision = revision;
46 * Return an interned reference to a equivalent QNameModule.
48 * @return Interned reference, or this object if it was interned.
50 public QNameModule intern() {
51 return INTERNER.intern(this);
55 * Create a new QName module instance with specified namespace/revision.
57 * @param namespace Module namespace
58 * @param revision Module revision
59 * @return A new, potentially shared, QNameModule instance
61 public static QNameModule create(final URI namespace, final Optional<Revision> revision) {
62 return new QNameModule(namespace, revision.isPresent() ? revision.get() : null);
66 * Create a new QName module instance with specified namespace and norevision.
68 * @param namespace Module namespace
69 * @return A new, potentially shared, QNameModule instance
71 @SuppressFBWarnings("NP_NULL_PARAM_DEREF_NONVIRTUAL")
72 public static QNameModule create(final URI namespace) {
73 return new QNameModule(namespace, null);
77 * Create a new QName module instance with specified namespace/revision.
79 * @param namespace Module namespace
80 * @param revision Module revision
81 * @return A new, potentially shared, QNameModule instance
83 public static QNameModule create(final URI namespace, @Nullable final Revision revision) {
84 return new QNameModule(namespace, revision);
88 * Read a QNameModule from a DataInput. The format is expected to match the output format
89 * of {@link #writeTo(DataOutput)}.
91 * @param in DataInput to read
92 * @return A QNameModule instance
93 * @throws IOException if I/O error occurs
95 public static 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));
102 * Returns the namespace of the module which is specified as argument of
103 * YANG Module <b><font color="#00FF00">namespace</font></b> keyword.
105 * @return URI format of the namespace of the module
107 public URI getNamespace() {
112 * Returns the revision date for the module.
114 * @return date of the module revision which is specified as argument of
115 * YANG Module <b><font color="#339900">revison</font></b> keyword
117 public Optional<Revision> getRevision() {
118 final Revision rev = revision;
119 return rev == null ? Optional.empty() : Optional.of(rev);
123 @SuppressWarnings("checkstyle:parameterName")
124 public int compareTo(final QNameModule o) {
125 int cmp = namespace.compareTo(o.namespace);
129 return Revision.compare(revision, o.revision);
133 * Returns a QNameModule with the same namespace, but with no revision. If this QNameModule does not have
134 * a revision, this object is returned.
136 * @return a QNameModule with the same namespace, but with no revision.
138 @SuppressFBWarnings("NP_NULL_PARAM_DEREF_NONVIRTUAL")
139 public QNameModule withoutRevision() {
140 return revision == null ? this : new QNameModule(namespace, null);
144 public void writeTo(final DataOutput out) throws IOException {
145 out.writeUTF(namespace.toString());
146 out.writeUTF(revision == null ? "" : revision.toString());
150 public int hashCode() {
152 hash = Objects.hash(namespace, revision);
158 public boolean equals(final @Nullable Object obj) {
162 if (!(obj instanceof QNameModule)) {
165 final QNameModule other = (QNameModule) obj;
166 return Objects.equals(revision, other.revision) && namespace.equals(other.namespace);
170 * Returns a namespace in form defined by section 5.6.4. of
171 * <a href=https://tools.ietf.org/html/rfc6020">RFC6020</a>, for example
172 * {@code http://example.acme.com/system?revision=2008-04-01}.
174 * @return Namespace in form defined by section 5.6.4. of RFC6020.
175 * @throws URISyntaxException on incorrect namespace definition
178 URI getRevisionNamespace() throws URISyntaxException {
179 final String query = revision == null ? "" : "revision=" + revision.toString();
180 return new URI(namespace.getScheme(), namespace.getUserInfo(), namespace.getHost(), namespace.getPort(),
181 namespace.getPath(), query, namespace.getFragment());
185 public String toString() {
186 return MoreObjects.toStringHelper(QNameModule.class).omitNullValues().add("ns", namespace)
187 .add("rev", revision).toString();