*/
package org.opendaylight.yangtools.yang.common;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.base.MoreObjects;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Date;
import java.util.Objects;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Identifier;
import org.opendaylight.yangtools.concepts.Immutable;
-import org.opendaylight.yangtools.objcache.ObjectCache;
-import org.opendaylight.yangtools.objcache.ObjectCacheFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.opendaylight.yangtools.concepts.WritableObject;
-public final class QNameModule implements Immutable, Serializable {
+public final class QNameModule implements Comparable<QNameModule>, Immutable, Serializable, Identifier, WritableObject {
private static final Interner<QNameModule> INTERNER = Interners.newWeakInterner();
- private static final ObjectCache CACHE = ObjectCacheFactory.getObjectCache(QNameModule.class);
- private static final Logger LOG = LoggerFactory.getLogger(QNameModule.class);
- private static final QNameModule NULL_INSTANCE = new QNameModule(null, null);
- private static final long serialVersionUID = 1L;
-
- //Nullable
- private final URI namespace;
+ private static final long serialVersionUID = 3L;
- //Nullable
- private final Date revision;
+ private final @NonNull URI namespace;
+ private final @Nullable Revision revision;
- //Nullable
- private volatile String formattedRevision;
+ private transient int hash = 0;
- private QNameModule(final URI namespace, final Date revision) {
- this.namespace = namespace;
+ private QNameModule(final URI namespace, final @Nullable Revision revision) {
+ this.namespace = requireNonNull(namespace);
this.revision = revision;
}
/**
- * Look up specified module in the global cache and return a shared reference.
+ * Return an interned reference to a equivalent QNameModule.
*
- * @param module Module instance
- * @return Cached instance, according to {@link ObjectCache} policy.
+ * @return Interned reference, or this object if it was interned.
+ */
+ public @NonNull QNameModule intern() {
+ return INTERNER.intern(this);
+ }
+
+ /**
+ * Create a new QName module instance with specified namespace/revision.
*
- * @deprecated Use {@link #intern()} instead.
+ * @param namespace Module namespace
+ * @param revision Module revision
+ * @return A new, potentially shared, QNameModule instance
+ * @throws NullPointerException if any argument is null
*/
- @Deprecated
- public static QNameModule cachedReference(final QNameModule module) {
- return CACHE.getReference(module);
+ public static @NonNull QNameModule create(final URI namespace, final Optional<Revision> revision) {
+ return new QNameModule(namespace, revision.orElse(null));
}
/**
- * Return an interned reference to a equivalent QNameModule.
+ * Create a new QName module instance with specified namespace and no revision.
*
- * @return Interned reference, or this object if it was interned.
+ * @param namespace Module namespace
+ * @return A new, potentially shared, QNameModule instance
+ * @throws NullPointerException if {@code namespace} is null
*/
- public QNameModule intern() {
- return INTERNER.intern(this);
+ public static @NonNull QNameModule create(final URI namespace) {
+ return new QNameModule(namespace, null);
}
/**
* @param namespace Module namespace
* @param revision Module revision
* @return A new, potentially shared, QNameModule instance
+ * @throws NullPointerException if any argument is null
*/
- public static QNameModule create(final URI namespace, final Date revision) {
- if (namespace == null && revision == null) {
- return NULL_INSTANCE;
- }
-
+ public static @NonNull QNameModule create(final URI namespace, final @Nullable Revision revision) {
return new QNameModule(namespace, revision);
}
- public String getFormattedRevision() {
- if (revision == null) {
- return null;
- }
-
- String ret = formattedRevision;
- if (ret == null) {
- ret = SimpleDateFormatUtil.getRevisionFormat().format(revision);
- formattedRevision = ret;
- }
-
- return ret;
+ /**
+ * Read a QNameModule from a DataInput. The format is expected to match the output format
+ * of {@link #writeTo(DataOutput)}.
+ *
+ * @param in DataInput to read
+ * @return A QNameModule instance
+ * @throws IOException if I/O error occurs
+ */
+ public static @NonNull QNameModule readFrom(final DataInput in) throws IOException {
+ final String namespace = in.readUTF();
+ final String revision = in.readUTF();
+ return new QNameModule(URI.create(namespace), revision.isEmpty() ? null : Revision.of(revision));
}
/**
- * Returns the namespace of the module which is specified as argument of
- * YANG Module <b><font color="#00FF00">namespace</font></b> keyword.
+ * Returns the namespace of the module which is specified as argument of YANG Module {@code namespace} keyword.
*
* @return URI format of the namespace of the module
*/
- public URI getNamespace() {
+ public @NonNull URI getNamespace() {
return namespace;
}
* @return date of the module revision which is specified as argument of
* YANG Module <b><font color="#339900">revison</font></b> keyword
*/
- public Date getRevision() {
- return revision;
+ public @NonNull Optional<Revision> getRevision() {
+ return Optional.ofNullable(revision);
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:parameterName")
+ public int compareTo(final QNameModule o) {
+ int cmp = namespace.compareTo(o.namespace);
+ if (cmp != 0) {
+ return cmp;
+ }
+ return Revision.compare(revision, o.revision);
+ }
+
+ /**
+ * Returns a QNameModule with the same namespace, but with no revision. If this QNameModule does not have
+ * a revision, this object is returned.
+ *
+ * @return a QNameModule with the same namespace, but with no revision.
+ */
+ public @NonNull QNameModule withoutRevision() {
+ return revision == null ? this : new QNameModule(namespace, null);
+ }
+
+ @Override
+ public void writeTo(final DataOutput out) throws IOException {
+ out.writeUTF(namespace.toString());
+ out.writeUTF(revision == null ? "" : revision.toString());
}
@Override
public int hashCode() {
- final int prime = 31;
- int result = Objects.hashCode(namespace);
- result = prime * result + Objects.hashCode(revision);
- return result;
+ if (hash == 0) {
+ hash = Objects.hash(namespace, revision);
+ }
+ return hash;
}
@Override
return false;
}
final QNameModule other = (QNameModule) obj;
- if (!Objects.equals(revision, other.revision)) {
- return false;
- }
- if (!Objects.equals(namespace, other.namespace)) {
- return false;
- }
- return true;
+ return Objects.equals(revision, other.revision) && namespace.equals(other.namespace);
}
/**
- * Returns a namespace in form defined by section 5.6.4. of {@link https
- * ://tools.ietf.org/html/rfc6020}, if namespace is not correctly defined,
- * the method will return <code>null</code> <br>
- * example "http://example.acme.com/system?revision=2008-04-01"
+ * Returns a namespace in form defined by section 5.6.4. of
+ * <a href=https://tools.ietf.org/html/rfc6020">RFC6020</a>, for example
+ * {@code http://example.acme.com/system?revision=2008-04-01}.
*
- * @return namespace in form defined by section 5.6.4. of {@link https
- * ://tools.ietf.org/html/rfc6020}, if namespace is not correctly
- * defined, the method will return <code>null</code>
+ * @return Namespace in form defined by section 5.6.4. of RFC6020.
+ * @throws URISyntaxException on incorrect namespace definition
*
*/
- URI getRevisionNamespace() {
-
- if (namespace == null) {
- return null;
- }
-
- String query = "";
- if (revision != null) {
- query = "revision=" + getFormattedRevision();
- }
-
- URI compositeURI = null;
- try {
- compositeURI = new URI(namespace.getScheme(), namespace.getUserInfo(), namespace.getHost(),
- namespace.getPort(), namespace.getPath(), query, namespace.getFragment());
- } catch (final URISyntaxException e) {
- LOG.error("", e);
- }
- return compositeURI;
+ @NonNull URI getRevisionNamespace() throws URISyntaxException {
+ final String query = revision == null ? "" : "revision=" + revision.toString();
+ return new URI(namespace.getScheme(), namespace.getUserInfo(), namespace.getHost(), namespace.getPort(),
+ namespace.getPath(), query, namespace.getFragment());
}
@Override
- public String toString() {
- return MoreObjects.toStringHelper(this).omitNullValues().add("ns", getNamespace()).add("rev", getFormattedRevision()).toString();
+ public @NonNull String toString() {
+ return MoreObjects.toStringHelper(QNameModule.class).omitNullValues().add("ns", namespace)
+ .add("rev", revision).toString();
}
}