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 java.io.DataInput;
16 import java.io.DataOutput;
17 import java.io.IOException;
18 import java.io.Serializable;
20 import java.net.URISyntaxException;
21 import java.util.Objects;
22 import java.util.Optional;
23 import javax.annotation.Nullable;
24 import org.eclipse.jdt.annotation.NonNull;
25 import org.opendaylight.yangtools.concepts.Identifier;
26 import org.opendaylight.yangtools.concepts.Immutable;
27 import org.opendaylight.yangtools.concepts.WritableObject;
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;
33 private final @NonNull URI namespace;
36 private final Revision revision;
38 private transient int hash = 0;
40 private QNameModule(final @NonNull URI namespace, final 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.orElse(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 public static QNameModule create(final URI namespace) {
72 return new QNameModule(namespace, null);
76 * Create a new QName module instance with specified namespace/revision.
78 * @param namespace Module namespace
79 * @param revision Module revision
80 * @return A new, potentially shared, QNameModule instance
82 public static QNameModule create(final URI namespace, @Nullable final Revision revision) {
83 return new QNameModule(namespace, revision);
87 * Read a QNameModule from a DataInput. The format is expected to match the output format
88 * of {@link #writeTo(DataOutput)}.
90 * @param in DataInput to read
91 * @return A QNameModule instance
92 * @throws IOException if I/O error occurs
94 public static 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));
101 * Returns the namespace of the module which is specified as argument of
102 * YANG Module <b><font color="#00FF00">namespace</font></b> keyword.
104 * @return URI format of the namespace of the module
106 public URI getNamespace() {
111 * Returns the revision date for the module.
113 * @return date of the module revision which is specified as argument of
114 * YANG Module <b><font color="#339900">revison</font></b> keyword
116 public Optional<Revision> getRevision() {
117 return Optional.ofNullable(revision);
121 @SuppressWarnings("checkstyle:parameterName")
122 public int compareTo(final QNameModule o) {
123 int cmp = namespace.compareTo(o.namespace);
127 return Revision.compare(revision, o.revision);
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.
134 * @return a QNameModule with the same namespace, but with no revision.
136 public QNameModule withoutRevision() {
137 return revision == null ? this : new QNameModule(namespace, null);
141 public void writeTo(final DataOutput out) throws IOException {
142 out.writeUTF(namespace.toString());
143 out.writeUTF(revision == null ? "" : revision.toString());
147 public int hashCode() {
149 hash = Objects.hash(namespace, revision);
155 public boolean equals(final Object obj) {
159 if (!(obj instanceof QNameModule)) {
162 final QNameModule other = (QNameModule) obj;
163 return Objects.equals(revision, other.revision) && namespace.equals(other.namespace);
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}.
171 * @return Namespace in form defined by section 5.6.4. of RFC6020.
172 * @throws URISyntaxException on incorrect namespace definition
175 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());
182 public String toString() {
183 return MoreObjects.toStringHelper(QNameModule.class).omitNullValues().add("ns", namespace)
184 .add("rev", revision).toString();