/** * 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.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.PublicAPI; /** * An immutable external identifier for an item. * <p> * This identifier is used as a handle within the system to refer to an externally defined identifier. * By contrast, the {@code ObjectId} and {@code UniqueId} represent identifiers within an OpenGamma system. * <p> * The external identifier is formed from two parts, the scheme and value. * 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. * <p> * Real-world examples of {@code ExternalId} include instances of: * <ul> * <li>Cusip</li> * <li>Isin</li> * <li>Reuters RIC</li> * <li>Bloomberg BUID</li> * <li>Bloomberg Ticker</li> * <li>Trading system OTC trade ID</li> * </ul> * <p> * This class is immutable and thread-safe. */ @PublicAPI public final class ExternalId implements ExternalIdentifiable, ExternalIdOrBundle, Comparable<ExternalId>, Serializable { /** Serialization version. */ private static final long serialVersionUID = 1L; /** * The scheme that categorizes the identifier value. */ private final ExternalScheme _scheme; /** * The identifier value within the scheme. */ private final String _value; /** * Obtains an {@code ExternalId} from a scheme and value. * * @param scheme the scheme of the external identifier, not empty, not null * @param value the value of the external identifier, not empty, not null * @return the external identifier, not null */ public static ExternalId of(ExternalScheme scheme, String value) { return new ExternalId(scheme, value); } /** * Obtains an {@code ExternalId} from a scheme and value. * * @param scheme the scheme of the external identifier, not empty, not null * @param value the value of the external identifier, not empty, not null * @return the external identifier, not null */ public static ExternalId of(String scheme, String value) { return new ExternalId(ExternalScheme.of(scheme), value); } /** * Parses an {@code ExternalId} from a formatted scheme and value. * <p> * This parses the identifier from the form produced by {@code toString()} * which is {@code <SCHEME>~<VALUE>}. * * @param str the external identifier to parse, not null * @return the external identifier, not null * @throws IllegalArgumentException if the identifier cannot be parsed */ @FromString public static ExternalId parse(String str) { ArgumentChecker.notEmpty(str, "str"); str = StringUtils.replace(str, "::", "~"); // leniently parse old data int pos = str.indexOf("~"); if (pos < 0) { throw new IllegalArgumentException("Invalid identifier format: " + str); } return new ExternalId(ExternalScheme.of(str.substring(0, pos)), str.substring(pos + 1)); } /** * Creates an external identifier. * * @param scheme the scheme, not null * @param value the value of the identifier, not empty, not null */ private ExternalId(ExternalScheme scheme, String value) { ArgumentChecker.notNull(scheme, "scheme"); ArgumentChecker.notEmpty(value, "value"); _scheme = scheme; _value = value; } //------------------------------------------------------------------------- /** * Gets the scheme of the identifier. * <p> * This provides the universe within which the identifier value has meaning. * * @return the scheme, not null */ public ExternalScheme getScheme() { return _scheme; } /** * Gets the value of the identifier. * * @return the value, not empty, not null */ public String getValue() { return _value; } //------------------------------------------------------------------------- /** * Checks if the scheme of this identifier equals the specified scheme. * * @param scheme the scheme to check for, null returns false * @return true if the schemes match */ public boolean isScheme(ExternalScheme scheme) { return _scheme.equals(scheme); } /** * Checks if the scheme of this identifier equals the specified scheme. * * @param scheme the scheme to check for, null returns false * @return true if the schemes match */ public boolean isScheme(String scheme) { return _scheme.getName().equals(scheme); } /** * Checks if the scheme of this identifier equals the specified scheme. * * @param scheme the scheme to check for, null returns true * @return true if the schemes are different */ public boolean isNotScheme(ExternalScheme scheme) { return _scheme.equals(scheme) == false; } /** * Checks if the scheme of this identifier equals the specified scheme. * * @param scheme the scheme to check for, null returns true * @return true if the schemes are different */ public boolean isNotScheme(String scheme) { return _scheme.getName().equals(scheme) == false; } //------------------------------------------------------------------------- /** * Gets the external identifier. * <p> * This method trivially returns {@code this}. * * @return {@code this}, not null */ @Override public ExternalId getExternalId() { return this; } /** * Converts this identifier to a bundle. * * @return a bundle wrapping this identifier, not null */ @Override public ExternalIdBundle toBundle() { return ExternalIdBundle.of(this); } //------------------------------------------------------------------------- /** * Compares the external identifiers, sorting alphabetically by scheme followed by value. * * @param other the other external identifier, not null * @return negative if this is less, zero if equal, positive if greater */ @Override public int compareTo(ExternalId other) { int cmp = _scheme.compareTo(other._scheme); if (cmp != 0) { return cmp; } return _value.compareTo(other._value); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof ExternalId) { ExternalId other = (ExternalId) obj; return _scheme.equals(other._scheme) && _value.equals(other._value); } return false; } @Override public int hashCode() { return _scheme.hashCode() ^ _value.hashCode(); } /** * Returns the identifier in the form {@code <SCHEME>~<VALUE>}. * * @return a parsable representation of the identifier, not null */ @Override @ToString public String toString() { return new StrBuilder().append(_scheme).append('~').append(_value).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) { ExternalIdFudgeBuilder.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 ExternalId fromFudgeMsg(final FudgeDeserializer deserializer, final FudgeMsg msg) { return ExternalIdFudgeBuilder.fromFudgeMsg(deserializer, msg); } }