X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-common%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fcommon%2FQName.java;h=c1bd85d23591f43f4a5c91491e0e566cac731fff;hb=refs%2Fchanges%2F18%2F35918%2F2;hp=5d2563d683c78f6cee5606fdbedc9b7052f9c760;hpb=a71d57dfd8b8a0f496dc7dafbc546960eed93791;p=yangtools.git diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QName.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QName.java index 5d2563d683..c1bd85d235 100644 --- a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QName.java +++ b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QName.java @@ -8,7 +8,9 @@ package org.opendaylight.yangtools.yang.common; import static org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil.getRevisionFormat; - +import com.google.common.base.Preconditions; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; @@ -17,10 +19,7 @@ import java.util.Date; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.opendaylight.yangtools.concepts.Immutable; -import org.opendaylight.yangtools.objcache.ObjectCache; -import org.opendaylight.yangtools.objcache.ObjectCacheFactory; /** * The QName from XML consists of local name of element and XML namespace, but @@ -47,7 +46,7 @@ import org.opendaylight.yangtools.objcache.ObjectCacheFactory; * */ public final class QName implements Immutable, Serializable, Comparable { - private static final ObjectCache CACHE = ObjectCacheFactory.getObjectCache(QName.class); + private static final Interner INTERNER = Interners.newWeakInterner(); private static final long serialVersionUID = 5398411242927766414L; static final String QNAME_REVISION_DELIMITER = "?revision="; @@ -64,42 +63,23 @@ public final class QName implements Immutable, Serializable, Comparable { private final QNameModule module; // Mandatory private final String localName; - // Nullable - private final String prefix; - private QName(final QNameModule module, final String prefix, final String localName) { + private QName(final QNameModule module, final String localName) { this.localName = checkLocalName(localName); - this.prefix = prefix; this.module = module; } /** * Look up specified QName in the global cache and return a shared reference. * - * @param module QName instance - * @return Cached instance, according to {@link ObjectCache} policy. - */ - public static QName cachedReference(final QName qname) { - return CACHE.getReference(qname); - } - - /** - * QName Constructor. - * - * @param namespace - * the namespace assigned to the YANG module - * @param revision - * the revision of the YANG module - * @param prefix - * locally defined prefix assigned to local name - * @param localName - * YANG schema identifier + * @param qname QName instance + * @return Cached instance, according to {@link org.opendaylight.yangtools.objcache.ObjectCache} policy. * - * @deprecated Prefix storage in QNames is deprecated. + * @deprecated Use {@link #intern()} instead. */ @Deprecated - public QName(final URI namespace, final Date revision, final String prefix, final String localName) { - this(QNameModule.create(namespace, revision), prefix, localName); + public static QName cachedReference(final QName qname) { + return qname.intern(); } /** @@ -111,7 +91,7 @@ public final class QName implements Immutable, Serializable, Comparable { * YANG schema identifier */ public QName(final URI namespace, final String localName) { - this(namespace, null, "", localName); + this(QNameModule.create(namespace, null), localName); } private static String checkLocalName(final String localName) { @@ -122,7 +102,7 @@ public final class QName implements Immutable, Serializable, Comparable { throw new IllegalArgumentException("Parameter 'localName' must be a non-empty string."); } - for (char c : ILLEGAL_CHARACTERS) { + for (final char c : ILLEGAL_CHARACTERS) { if (localName.indexOf(c) != -1) { throw new IllegalArgumentException(String.format( "Parameter 'localName':'%s' contains illegal character '%s'", localName, c)); @@ -134,20 +114,20 @@ public final class QName implements Immutable, Serializable, Comparable { public static QName create(final String input) { Matcher matcher = QNAME_PATTERN_FULL.matcher(input); if (matcher.matches()) { - String namespace = matcher.group(1); - String revision = matcher.group(2); - String localName = matcher.group(3); + final String namespace = matcher.group(1); + final String revision = matcher.group(2); + final String localName = matcher.group(3); return create(namespace, revision, localName); } matcher = QNAME_PATTERN_NO_REVISION.matcher(input); if (matcher.matches()) { - URI namespace = URI.create(matcher.group(1)); - String localName = matcher.group(2); + final URI namespace = URI.create(matcher.group(1)); + final String localName = matcher.group(2); return new QName(namespace, localName); } matcher = QNAME_PATTERN_NO_NAMESPACE_NO_REVISION.matcher(input); if (matcher.matches()) { - String localName = matcher.group(1); + final String localName = matcher.group(1); return new QName((URI) null, localName); } throw new IllegalArgumentException("Invalid input:" + input); @@ -194,22 +174,27 @@ public final class QName implements Immutable, Serializable, Comparable { } /** - * Returns locally defined prefix assigned to local name - * - * @return locally defined prefix assigned to local name + * Return an interned reference to a equivalent QName. * - * @deprecated Prefix storage in QNames is deprecated. + * @return Interned reference, or this object if it was interned. */ - @Deprecated - public String getPrefix() { - return prefix; + public QName intern() { + // We also want to make sure we keep the QNameModule cached + final QNameModule cacheMod = module.intern(); + + // Identity comparison is here on purpose, as we are deciding whether to potentially store 'qname' into the + // interner. It is important that it does not hold user-supplied reference (such a String instance from + // parsing of an XML document). + final QName template = cacheMod == module ? this : QName.create(cacheMod, localName); + + return INTERNER.intern(template); } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((localName == null) ? 0 : localName.hashCode()); + result = prime * result + Objects.hashCode(localName); result = prime * result + module.hashCode(); return result; } @@ -221,7 +206,7 @@ public final class QName implements Immutable, Serializable, Comparable { * {@link QName} and its {@link #getLocalName()}, {@link #getNamespace()} and * {@link #getRevision()} are equals to same properties of this instance. * - * @param o the object to be compared for equality with this QName + * @param obj the object to be compared for equality with this QName * @return true if the specified object is equal to this QName * */ @@ -234,39 +219,11 @@ public final class QName implements Immutable, Serializable, Comparable { return false; } final QName other = (QName) obj; - if (localName == null) { - if (other.localName != null) { - return false; - } - } else if (!localName.equals(other.localName)) { - return false; - } - return module.equals(other.module); + return Objects.equals(localName, other.localName) && module.equals(other.module); } public static QName create(final QName base, final String localName) { - return create(base.getModule(), base.getPrefix(), localName); - } - - /** - * Creates new QName. - * - * @param qnameModule - * Namespace and revision enclosed as a QNameModule - * @param prefix - * Namespace prefix - * @param localName - * Local name part of QName. MUST NOT BE null. - * @return Instance of QName - * - * @deprecated Prefix storage in QNames is deprecated. - */ - @Deprecated - public static QName create(final QNameModule module, final String prefix, final String localName) { - if (module == null) { - throw new NullPointerException("module may not be null"); - } - return new QName(module, prefix, localName); + return create(base.getModule(), localName); } /** @@ -279,7 +236,7 @@ public final class QName implements Immutable, Serializable, Comparable { * @return Instance of QName */ public static QName create(final QNameModule qnameModule, final String localName) { - return create(qnameModule, null, localName); + return new QName(Preconditions.checkNotNull(qnameModule,"module may not be null"), localName); } /** @@ -294,7 +251,7 @@ public final class QName implements Immutable, Serializable, Comparable { * @return Instance of QName */ public static QName create(final URI namespace, final Date revision, final String localName) { - return create(QNameModule.create(namespace, revision), null, localName); + return create(QNameModule.create(namespace, revision), localName); } /** @@ -310,33 +267,51 @@ public final class QName implements Immutable, Serializable, Comparable { * Local name part of QName. MUST NOT BE null. * @return * @throws NullPointerException - * If any of paramaters is null. + * If any of parameters is null. * @throws IllegalArgumentException * If namespace is not valid URI or * revision is not according to format * YYYY-mm-dd. */ - public static QName create(final String namespace, final String revision, final String localName) - throws IllegalArgumentException { - final URI namespaceUri; + public static QName create(final String namespace, final String revision, final String localName) { + final URI namespaceUri = parseNamespace(namespace); + final Date revisionDate = parseRevision(revision); + return create(namespaceUri, revisionDate, localName); + } + + private static URI parseNamespace(final String namespace) { try { - namespaceUri = new URI(namespace); - } catch (URISyntaxException ue) { + return new URI(namespace); + } catch (final URISyntaxException ue) { throw new IllegalArgumentException(String.format("Namespace '%s' is not a valid URI", namespace), ue); } + } - Date revisionDate = parseRevision(revision); - return create(namespaceUri, revisionDate, localName); + /** + * Creates new QName. + * + * @param namespace + * Namespace of QName, MUST NOT BE Null. + * @param localName + * Local name part of QName. MUST NOT BE null. + * @return + * @throws NullPointerException + * If any of parameters is null. + * @throws IllegalArgumentException + * If namespace is not valid URI. + */ + public static QName create(final String namespace, final String localName) { + return create(parseNamespace(namespace), null, localName); } @Override public String toString() { - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); if (getNamespace() != null) { - sb.append(QNAME_LEFT_PARENTHESIS + getNamespace()); + sb.append(QNAME_LEFT_PARENTHESIS).append(getNamespace()); if (getFormattedRevision() != null) { - sb.append(QNAME_REVISION_DELIMITER + getFormattedRevision()); + sb.append(QNAME_REVISION_DELIMITER).append(getFormattedRevision()); } sb.append(QNAME_RIGHT_PARENTHESIS); }