Move yang-common(-netty)
[yangtools.git] / common / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / QNameModule.java
diff --git a/common/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QNameModule.java b/common/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QNameModule.java
new file mode 100644 (file)
index 0000000..0221ecc
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+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.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.concepts.WritableObject;
+
+public final class QNameModule implements Comparable<QNameModule>, Immutable, Serializable, Identifier, WritableObject {
+    private static final Interner<QNameModule> INTERNER = Interners.newWeakInterner();
+    private static final long serialVersionUID = 3L;
+
+    private final @NonNull XMLNamespace namespace;
+    private final @Nullable Revision revision;
+
+    private transient int hash = 0;
+
+    private QNameModule(final XMLNamespace namespace, final @Nullable Revision revision) {
+        this.namespace = requireNonNull(namespace);
+        this.revision = revision;
+    }
+
+    /**
+     * Return an interned reference to a equivalent QNameModule.
+     *
+     * @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.
+     *
+     * @param namespace Module namespace
+     * @param revision Module revision
+     * @return A new, potentially shared, QNameModule instance
+     * @throws NullPointerException if any argument is null
+     */
+    public static @NonNull QNameModule create(final XMLNamespace namespace, final Optional<Revision> revision) {
+        return new QNameModule(namespace, revision.orElse(null));
+    }
+
+    /**
+     * Create a new QName module instance with specified namespace and no revision.
+     *
+     * @param namespace Module namespace
+     * @return A new, potentially shared, QNameModule instance
+     * @throws NullPointerException if {@code namespace} is null
+     */
+    public static @NonNull QNameModule create(final XMLNamespace namespace) {
+        return new QNameModule(namespace, null);
+    }
+
+    /**
+     * Create a new QName module instance with specified namespace/revision.
+     *
+     * @param namespace Module namespace
+     * @param revision Module revision
+     * @return A new, potentially shared, QNameModule instance
+     * @throws NullPointerException if any argument is null
+     */
+    public static @NonNull QNameModule create(final XMLNamespace namespace, final @Nullable Revision revision) {
+        return new QNameModule(namespace, revision);
+    }
+
+    /**
+     * 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(XMLNamespace.of(namespace), revision.isEmpty() ? null : Revision.of(revision));
+    }
+
+    /**
+     * Returns the namespace of the module which is specified as argument of YANG Module {@code namespace} keyword.
+     *
+     * @return XMLNamespace of the namespace of the module
+     */
+    public @NonNull XMLNamespace getNamespace() {
+        return namespace;
+    }
+
+    /**
+     * Returns the revision date for the module.
+     *
+     * @return date of the module revision which is specified as argument of YANG Module {@code revision} keyword
+     */
+    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() {
+        if (hash == 0) {
+            hash = Objects.hash(namespace, revision);
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof QNameModule)) {
+            return false;
+        }
+        final QNameModule other = (QNameModule) obj;
+        return Objects.equals(revision, other.revision) && namespace.equals(other.namespace);
+    }
+
+    @Override
+    public @NonNull String toString() {
+        return MoreObjects.toStringHelper(QNameModule.class).omitNullValues().add("ns", namespace)
+            .add("rev", revision).toString();
+    }
+
+    Object writeReplace() {
+        return new NSv1(this);
+    }
+}