package org.marketcetera.algo; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.xml.bind.annotation.*; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.marketcetera.core.CoreException; import org.marketcetera.core.Validator; import org.marketcetera.trade.NewOrReplaceOrder; import org.marketcetera.util.log.I18NBoundMessage2P; import org.marketcetera.util.misc.ClassVersion; /* $License$ */ /** * Represents a broker algorithm bound with user-supplied values. * * @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a> * @version $Id: BrokerAlgo.java 16901 2014-05-11 16:14:11Z colin $ * @since 2.4.0 */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @ClassVersion("$Id: BrokerAlgo.java 16901 2014-05-11 16:14:11Z colin $") public class BrokerAlgo implements Serializable { /** * Create a new BrokerAlgo instance. */ public BrokerAlgo() {} /** * Create a new BrokerAlgo instance. * * @param inSpec a <code>BrokerAlgoSpec</code> value */ public BrokerAlgo(BrokerAlgoSpec inSpec) { setAlgoSpec(inSpec); } /** * Create a new BrokerAlgo instance. * * @param inSpec a <code>BrokerAlgoSpec</code> value * @param inTags a <code>Set<BrokerAlgoTag></code> value */ public BrokerAlgo(BrokerAlgoSpec inSpec, Set<BrokerAlgoTag> inTags) { setAlgoSpec(inSpec); setAlgoTags(inTags); } /** * Get the algoSpec value. * * @return a <code>BrokerAlgoSpec</code> value */ public BrokerAlgoSpec getAlgoSpec() { return algoSpec; } /** * Sets the algoSpec value. * * @param inAlgoSpec a <code>BrokerAlgoSpec</code> value */ public final void setAlgoSpec(BrokerAlgoSpec inAlgoSpec) { algoSpec = inAlgoSpec; } /** * Get the algoTags value. * * @return a <code>Set<BrokerAlgoTag></code> value */ public Set<BrokerAlgoTag> getAlgoTags() { return algoTags; } /** * Sets the algoTags value. * * @param inAlgoTags a <code>Set<BrokerAlgoTag></code> value */ public final void setAlgoTags(Set<BrokerAlgoTag> inAlgoTags) { algoTags = inAlgoTags; } /** * Applies the implied tags and values of the broker algo to the given order. * * @param inOrder a <code>NewOrReplaceOrder</code> value */ public void applyTo(NewOrReplaceOrder inOrder) { if(algoTags == null) { return; } Map<String,String> customFields = inOrder.getCustomFields(); if(customFields == null) { customFields = new HashMap<String,String>(); } for(BrokerAlgoTag algoTag : algoTags) { customFields.put(String.valueOf(algoTag.getTagSpec().getTag()), algoTag.getValue()); } inOrder.setCustomFields(customFields); } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("BrokerAlgo [algoSpec=").append(algoSpec).append(", algoTags=").append(algoTags).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return builder.toString(); } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return new HashCodeBuilder().append(algoSpec).append(algoTags).toHashCode(); } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; BrokerAlgo other = (BrokerAlgo) obj; return new EqualsBuilder().append(algoSpec,other.algoSpec).append(algoTags,other.algoTags).isEquals(); } /** * Maps validators from the given cannonical algo spec to this algo spec. * * <p>If this object's <code>BrokerAlgoSpec</code> is <code>null</code>, this method has no effect. * * @param inCannonicalAlgoSpec a <code>BrokerAlgoSpec</code> value * @throws CoreException if the given <code>BrokerAlgoSpec</code> is not the same as this object's <code>BrokerAlgoSpec</code> */ public void mapValidatorsFrom(BrokerAlgoSpec inCannonicalAlgoSpec) { if(algoSpec == null) { return; } if(!algoSpec.equals(inCannonicalAlgoSpec)) { throw new CoreException(new I18NBoundMessage2P(Messages.ALGO_SPEC_MISMATCH, algoSpec.getName(), inCannonicalAlgoSpec.getName())); } algoSpec.setValidator(inCannonicalAlgoSpec.getValidator()); if(algoTags != null && inCannonicalAlgoSpec.getAlgoTagSpecs() != null) { Map<Integer,Validator<BrokerAlgoTag>> validators = new HashMap<Integer,Validator<BrokerAlgoTag>>(); for(BrokerAlgoTagSpec algoTagSpec : inCannonicalAlgoSpec.getAlgoTagSpecs()) { if(algoTagSpec.getValidator() != null) { validators.put(algoTagSpec.getTag(), algoTagSpec.getValidator()); } } for(BrokerAlgoTag algoTag : algoTags) { algoTag.getTagSpec().setValidator(validators.get(algoTag.getTagSpec().getTag())); } } } /** * Validates the bound broker algo. * * <p>This method will not completely validate the algo unless {@link #mapValidatorsFrom(BrokerAlgoSpec)} * has been invoked with the cannonical broker algo spec first. * @throws RuntimeException if validation fails */ public void validate() { // perform spec-by-spec validation if(algoTags != null) { for(BrokerAlgoTag tag : algoTags) { tag.validate(); } } // perform top-level validation if(algoSpec != null) { Validator<BrokerAlgo> algoValidator = algoSpec.getValidator(); if(algoValidator != null) { algoValidator.validate(this); } } } /** * contains the broker algo template */ @XmlElement private BrokerAlgoSpec algoSpec; /** * contains the broker algo tag values */ @XmlElementWrapper(name="algoTags") @XmlElement(name="tag",type=BrokerAlgoTag.class) private Set<BrokerAlgoTag> algoTags; private static final long serialVersionUID = -9165368996244848275L; }