/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine; import java.io.ObjectStreamException; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.text.StrBuilder; import com.opengamma.core.position.PortfolioNode; import com.opengamma.core.position.Position; import com.opengamma.core.position.Trade; import com.opengamma.core.security.Security; import com.opengamma.engine.target.ComputationTargetReference; import com.opengamma.engine.target.ComputationTargetReferenceVisitor; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.id.UniqueId; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.PublicAPI; import com.opengamma.util.credit.CreditCurveIdentifier; import com.opengamma.util.money.Currency; /** * An immutable specification of a particular computation target that will be resolved later on in a computation process to the actual target. */ @PublicAPI public final class ComputationTargetSpecification extends ComputationTargetReference { // [PLAT-444]: move to com.opengamma.engine.target /** * An specification that describes a target value of null. This will always be resolved to a {@link ComputationTarget} that contains a type of {@link ComputationTargetType#NULL} and a null value. It * can be used when the function is self describing and can gain no behavioral information from the target. */ public static final ComputationTargetSpecification NULL = MemoryUtils.instance(new ComputationTargetSpecification(ComputationTargetType.NULL, null)); private static final long serialVersionUID = 1L; /** * The identifier of the target. */ private final UniqueId _uniqueId; /** * Creates a lightweight specification of a computation target. * * @param targetType the type of the target, not null * @param uid the target identifier, may be null for the {@link ComputationTargetType#NULL} target type only */ public ComputationTargetSpecification(final ComputationTargetType targetType, final UniqueId uid) { super(targetType); if (targetType == ComputationTargetType.NULL) { ArgumentChecker.isTrue(uid == null, "uid"); } else { ArgumentChecker.notNull(uid, "uid"); } _uniqueId = uid; } public/* [PLAT-444]: should be package visible */ComputationTargetSpecification(final ComputationTargetType type, final UniqueId uid, final ComputationTargetReference parent) { super(type, parent); _uniqueId = uid; } public/* [PLAT-444]: should be package visible */ComputationTargetSpecification(final ComputationTargetReference parent, final ComputationTargetType type, final UniqueId uid) { super(parent, type); _uniqueId = uid; } /** * Creates a specification that will reference a portfolio node. * * @param portfolioNode the node that will be the target, not null * @return the target specification, not null */ public static ComputationTargetSpecification of(final PortfolioNode portfolioNode) { return ComputationTargetType.PORTFOLIO_NODE.specification(portfolioNode); } /** * Creates a specification that will reference a position. * * @param position the position that will be the target, not null * @return the target specification, not null */ public static ComputationTargetSpecification of(final Position position) { return ComputationTargetType.POSITION.specification(position); } /** * Creates a specification that will reference a security. * * @param security the security that will be the target, not null * @return the target specification, not null */ public static ComputationTargetSpecification of(final Security security) { return ComputationTargetType.SECURITY.specification(security); } /** * Creates a specification that will reference a trade. * * @param trade the trade that will be the target, not null * @return the target specification, not null */ public static ComputationTargetSpecification of(final Trade trade) { return ComputationTargetType.TRADE.specification(trade); } /** * Creates a specification that describes a currency. A currency may be used as an arbitrary parameter to a function, for example one that provides curve definitions or other meta data that is keyed * by currency. * * @param currency the currency described, not null * @return the target specification, not null */ public static ComputationTargetSpecification of(final Currency currency) { return ComputationTargetType.CURRENCY.specification(currency); } /** * Creates a specification that describes a credit curve identifier. A credit curve identifier may be used as an arbitrary parameter to a function, for example one that provides spread curve * definitions or other meta data that is keyed by id. * * @param creditCurveIdentifier the credit curve identifier described, not null * @return the target specification, not null */ public static ComputationTargetSpecification of(final CreditCurveIdentifier creditCurveIdentifier) { return ComputationTargetType.CREDIT_CURVE_IDENTIFIER.specification(creditCurveIdentifier); } /** * Creates a specification that describes an arbitrary target. The unique identifier is not resolved to a target but will be presented as an arbitrary parameter to a function. * * @param uniqueId the identifier to hold, not null * @return the target specification, not null */ public static ComputationTargetSpecification of(final UniqueId uniqueId) { return new ComputationTargetSpecification(ComputationTargetType.PRIMITIVE, uniqueId); } /** * Gets the unique identifier, if one exists. * * @return the unique identifier, may be null if the target type is {@link ComputationTargetType#NULL} */ public UniqueId getUniqueId() { return _uniqueId; } /** * Tests if this specification is compatible with another. To be compatible, the target types must be compatible and the unique identifier chain match at each level. * * @param other the target specification to test against, not null * @return true if the object described by the supplied specification is suitable for this specification */ public boolean isCompatible(final ComputationTargetSpecification other) { if (!getType().isCompatible(other.getType())) { return false; } // TODO: should be checking the parent as well return ObjectUtils.equals(getUniqueId(), other.getUniqueId()); } @Override public ComputationTargetSpecification getSpecification() { return this; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj instanceof ComputationTargetSpecification) { final ComputationTargetSpecification other = (ComputationTargetSpecification) obj; return super.equals(obj) && ObjectUtils.equals(_uniqueId, other._uniqueId); } return false; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); if (_uniqueId != null) { result = prime * result + _uniqueId.hashCode(); } return result; } @Override protected String getIdStringImpl() { if (getUniqueId() != null) { return getUniqueId().toString(); } else { return "NULL"; } } @Override public String toString() { return new StrBuilder() .append("CTSpec[") .append(getType()) .append(", ") .append(getIdString()) .append(']') .toString(); } private Object readResolve() throws ObjectStreamException { return MemoryUtils.instance(this); } @Override protected ComputationTargetSpecification create(final ComputationTargetReference parent, final ComputationTargetType type) { return new ComputationTargetSpecification(parent, type, getUniqueId()); } @Override public <T> T accept(final ComputationTargetReferenceVisitor<T> visitor) { return visitor.visitComputationTargetSpecification(this); } }