com.opengamma.id.UniqueId.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.id.UniqueId.java

Source

/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.id;

import java.io.Serializable;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrBuilder;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.mapping.FudgeDeserializer;
import org.fudgemsg.mapping.FudgeSerializer;
import org.joda.convert.FromString;
import org.joda.convert.ToString;

import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.CompareUtils;
import com.opengamma.util.PublicAPI;

/**
 * An immutable unique identifier for an item within the OpenGamma installation.
 * <p>
 * This identifier is used as a handle within the system to refer to an item uniquely.
 * All versions of the same object share an {@link ObjectId} with the
 * {@code UniqueId} referring to a single version.
 * <p>
 * Many external identifiers, represented by {@link ExternalId}, are not truly unique.
 * This {@code ObjectId} and {@code UniqueId} are unique within the OpenGamma instance.
 * <p>
 * The unique identifier is formed from three parts, the scheme, value and version.
 * The scheme defines a single way of identifying items, while the value is an identifier
 * within that scheme. A value from one scheme may refer to a completely different
 * real-world item than the same value from a different scheme.
 * The version allows the object being identifier to change over time.
 * If the version is null then the identifier refers to the latest version of the object.
 * Note that some data providers may not support versioning.
 * <p>
 * Real-world examples of {@code UniqueId} include instances of:
 * <ul>
 * <li>Database key - DbSec~123456~1</li>
 * <li>In memory key - MemSec~123456~234</li>
 * </ul>
 * <p>
 * This class is immutable and thread-safe.
 */
@PublicAPI
public final class UniqueId implements Comparable<UniqueId>, UniqueIdentifiable, ObjectIdentifiable, Serializable {

    /**
     * Identification scheme for the unique identifier.
     * This allows a unique identifier to be stored and passed using an {@code ExternalId}.
     */
    public static final ExternalScheme EXTERNAL_SCHEME = ExternalScheme.of("UID");

    /** Serialization version. */
    private static final long serialVersionUID = 1L;

    /**
     * The scheme that categorizes the identifier value.
     */
    private final String _scheme;
    /**
     * The identifier value within the scheme.
     */
    private final String _value;
    /**
     * The version of the identifier, null if latest or not-versioned.
     */
    private final String _version;

    /**
     * Obtains a {@code UniqueId} from a scheme and value indicating the latest version
     * of the identifier, also used for non-versioned identifiers.
     * 
     * @param scheme  the scheme of the identifier, not empty, not null
     * @param value  the value of the identifier, not empty, not null
     * @return the unique identifier, not null
     */
    public static UniqueId of(String scheme, String value) {
        return of(scheme, value, null);
    }

    /**
     * Obtains a {@code UniqueId} from a scheme, value and version.
     * 
     * @param scheme  the scheme of the identifier, not empty, not null
     * @param value  the value of the identifier, not empty, not null
     * @param version  the version of the identifier, empty treated as null, null treated as latest version
     * @return the unique identifier, not null
     */
    public static UniqueId of(String scheme, String value, String version) {
        return new UniqueId(scheme, value, version);
    }

    /**
     * Obtains a {@code UniqueId} from an {@code ObjectId} and a version.
     * 
     * @param objectId  the object identifier, not null
     * @param version  the version of the identifier, empty treated as null, null treated as latest version
     * @return the unique identifier, not null
     */
    public static UniqueId of(ObjectId objectId, String version) {
        ArgumentChecker.notNull(objectId, "objectId");
        return new UniqueId(objectId.getScheme(), objectId.getValue(), version);
    }

    /**
     * Obtains a {@code UniqueId} from an external identifier.
     * <p>
     * This allows a unique identifier that was previously packaged as an
     * {@link ExternalId} to be converted back. See {@link #toExternalId()}.
     * In general, this approach should be avoided.
     * 
     * @param externalId  the external identifier key, not null
     * @return the unique identifier, not null
     */
    public static UniqueId of(ExternalId externalId) {
        if (externalId.isNotScheme(EXTERNAL_SCHEME)) {
            throw new IllegalArgumentException("ExternalId is not a valid UniqueId");
        }
        return parse(externalId.getValue());
    }

    /**
     * Parses a {@code UniqueId} from a formatted scheme and value.
     * <p>
     * This parses the identifier from the form produced by {@code toString()}
     * which is {@code <SCHEME>~<VALUE>~<VERSION>}.
     * 
     * @param str  the unique identifier to parse, not null
     * @return the unique identifier, not null
     * @throws IllegalArgumentException if the identifier cannot be parsed
     */
    @FromString
    public static UniqueId parse(String str) {
        ArgumentChecker.notEmpty(str, "str");
        if (str.contains("~") == false) {
            str = StringUtils.replace(str, "::", "~"); // leniently parse old data
        }
        String[] split = StringUtils.splitByWholeSeparatorPreserveAllTokens(str, "~");
        switch (split.length) {
        case 2:
            return UniqueId.of(split[0], split[1], null);
        case 3:
            return UniqueId.of(split[0], split[1], split[2]);
        }
        throw new IllegalArgumentException("Invalid identifier format: " + str);
    }

    /**
     * Creates a unique instance.
     * 
     * @param scheme  the scheme of the identifier, not empty, not null
     * @param value  the value of the identifier, not empty, not null
     * @param version  the version of the identifier, null if latest version
     */
    private UniqueId(String scheme, String value, String version) {
        ArgumentChecker.notEmpty(scheme, "scheme");
        ArgumentChecker.notEmpty(value, "value");
        _scheme = scheme;
        _value = value;
        _version = StringUtils.trimToNull(version);
    }

    //-------------------------------------------------------------------------
    /**
     * Gets the scheme of the identifier.
     * This is the first part of the unique identifier.
     * <p>
     * This is not expected to be the same as {@link ExternalScheme}.
     * 
     * @return the scheme, not empty, not null
     */
    public String getScheme() {
        return _scheme;
    }

    /**
     * Gets the value of the identifier.
     * This is the second part of the unique identifier.
     * 
     * @return the value, not empty, not null
     */
    public String getValue() {
        return _value;
    }

    /**
     * Gets the version of the identifier.
     * This is the third part of the unique identifier.
     * 
     * @return the version, null if latest version
     */
    public String getVersion() {
        return _version;
    }

    //-------------------------------------------------------------------------
    /**
     * Returns a copy of this identifier with the specified scheme.
     * 
     * @param scheme  the new scheme of the identifier, not empty, not null
     * @return an {@link ObjectId} based on this identifier with the specified scheme, not null
     */
    public UniqueId withScheme(final String scheme) {
        return UniqueId.of(scheme, _value, _version);
    }

    /**
     * Returns a copy of this identifier with the specified value.
     * 
     * @param value  the new value of the identifier, not empty, not null
     * @return an {@link ObjectId} based on this identifier with the specified value, not null
     */
    public UniqueId withValue(final String value) {
        return UniqueId.of(_scheme, value, _version);
    }

    /**
     * Returns a copy of this identifier with the specified version.
     * 
     * @param version  the new version of the identifier, empty treated as null, null treated as latest version
     * @return the created identifier with the specified version, not null
     */
    public UniqueId withVersion(final String version) {
        if (ObjectUtils.equals(version, _version)) {
            return this;
        }
        return new UniqueId(_scheme, _value, version);
    }

    //-------------------------------------------------------------------------
    /**
     * Gets the object identifier.
     * <p>
     * All versions of the same object share the same object identifier.
     * 
     * @return the scheme, not empty, not null
     */
    @Override
    public ObjectId getObjectId() {
        return ObjectId.of(_scheme, _value);
    }

    /**
     * Gets the unique identifier.
     * <p>
     * This method trivially returns {@code this}.
     * 
     * @return {@code this}, not null
     */
    @Override
    public UniqueId getUniqueId() {
        return this;
    }

    //-------------------------------------------------------------------------
    /**
     * Checks if this represents the latest version of the item.
     * <p>
     * This simply checks if the version is null.
     * 
     * @return true if this is the latest version
     */
    public boolean isLatest() {
        return _version == null;
    }

    /**
     * Checks if this represents a versioned reference to the item.
     * <p>
     * This simply checks if the version is non null.
     * 
     * @return true if this is a versioned reference
     */
    public boolean isVersioned() {
        return _version != null;
    }

    /**
     * Returns a unique identifier based on this with the version set to null.
     * <p>
     * The returned identifier will represent the latest version of the item.
     * 
     * @return an identifier representing the latest version of the item, not null
     */
    public UniqueId toLatest() {
        if (isVersioned()) {
            return new UniqueId(_scheme, _value, null);
        } else {
            return this;
        }
    }

    /**
     * Converts this unique identifier to an external identifier.
     * <p>
     * This allows a unique identifier to be packaged and passed around
     * in the form of an external identifier. See {@link #of(ExternalId)}.
     * In general, this approach should be avoided.
     * 
     * @return the external identifier, not null
     */
    public ExternalId toExternalId() {
        return ExternalId.of(EXTERNAL_SCHEME, toString());
    }

    //-------------------------------------------------------------------------
    /**
     * Compares this identifier to another based on the object identifier, ignoring the version.
     * <p>
     * This checks to see if two unique identifiers represent the same underlying object.
     * 
     * @param other  the other identifier, null returns false
     * @return true if the object identifier are equal, ignoring the version
     */
    public boolean equalObjectId(ObjectIdentifiable other) {
        if (other == null) {
            return false;
        }
        ObjectId objectId = other.getObjectId();
        return _scheme.equals(objectId.getScheme()) && _value.equals(objectId.getValue());
    }

    //-------------------------------------------------------------------------
    /**
     * Compares the unique identifiers, sorting alphabetically by scheme followed by value.
     * 
     * @param other  the other unique identifier, not null
     * @return negative if this is less, zero if equal, positive if greater
     */
    @Override
    public int compareTo(UniqueId other) {
        int cmp = _scheme.compareTo(other._scheme);
        if (cmp != 0) {
            return cmp;
        }
        cmp = _value.compareTo(other._value);
        if (cmp != 0) {
            return cmp;
        }
        return CompareUtils.compareWithNullLow(_version, other._version);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof UniqueId) {
            UniqueId other = (UniqueId) obj;
            return _scheme.equals(other._scheme) && _value.equals(other._value)
                    && ObjectUtils.equals(_version, other._version);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return _scheme.hashCode() ^ _value.hashCode() ^ ObjectUtils.hashCode(_version);
    }

    /**
     * Returns the identifier in the form {@code <SCHEME>~<VALUE>~<VERSION>}.
     * <p>
     * If the version is null, the identifier will omit the colons and version.
     * 
     * @return a parsable representation of the identifier, not null
     */
    @Override
    @ToString
    public String toString() {
        StrBuilder buf = new StrBuilder().append(_scheme).append('~').append(_value);
        if (_version != null) {
            buf.append('~').append(_version);
        }
        return buf.toString();
    }

    //-------------------------------------------------------------------------
    /**
     * This is for more efficient code within the .proto representations of securities, allowing this class
     * to be used directly as a message type instead of through the serialization framework.
     * 
     * @param serializer  the serializer, not null
     * @param msg  the message to populate, not null
     * @deprecated Use builder
     */
    @Deprecated
    public void toFudgeMsg(final FudgeSerializer serializer, final MutableFudgeMsg msg) {
        UniqueIdFudgeBuilder.toFudgeMsg(serializer, this, msg);
    }

    /**
     * This is for more efficient code within the .proto representations of securities, allowing this class
     * to be used directly as a message type instead of through the serialization framework.
     * 
     * @param deserializer  the deserializer, not null
     * @param msg  the message to decode, not null
     * @return the created object, not null
     * @deprecated Use builder
     */
    @Deprecated
    public static UniqueId fromFudgeMsg(final FudgeDeserializer deserializer, final FudgeMsg msg) {
        return UniqueIdFudgeBuilder.fromFudgeMsg(deserializer, msg);
    }

}