package org.atdl4j.ui.impl;
import java.util.List;
import org.apache.log4j.Logger;
import org.atdl4j.config.Atdl4jOptions;
import org.atdl4j.config.InputAndFilterData;
import org.atdl4j.data.Atdl4jConstants;
import org.atdl4j.data.ControlTypeConverter;
import org.atdl4j.data.ParameterHelper;
import org.atdl4j.data.ParameterTypeConverter;
import org.atdl4j.data.TypeConverterFactoryConfig;
import org.atdl4j.data.fix.FIXMessageBuilder;
import org.atdl4j.data.fix.StringFIXMessageBuilder;
import org.atdl4j.data.fix.Tag959Helper;
import org.atdl4j.fixatdl.core.EnumPairT;
import org.atdl4j.fixatdl.core.ParameterT;
import org.atdl4j.fixatdl.layout.CheckBoxListT;
import org.atdl4j.fixatdl.layout.CheckBoxT;
import org.atdl4j.fixatdl.layout.ControlT;
import org.atdl4j.fixatdl.layout.DropDownListT;
import org.atdl4j.fixatdl.layout.EditableDropDownListT;
import org.atdl4j.fixatdl.layout.HiddenFieldT;
import org.atdl4j.fixatdl.layout.ListItemT;
import org.atdl4j.fixatdl.layout.MultiSelectListT;
import org.atdl4j.fixatdl.layout.RadioButtonListT;
import org.atdl4j.fixatdl.layout.RadioButtonT;
import org.atdl4j.fixatdl.layout.SingleSelectListT;
import org.atdl4j.fixatdl.layout.SliderT;
import org.atdl4j.fixatdl.layout.StrategyPanelT;
import org.atdl4j.ui.Atdl4jWidget;
/**
* Abstract class that represents a Parameter Widget. Implements the FIX
* value getters's methods.
*/
public abstract class AbstractAtdl4jWidget<E extends Comparable<?>>
implements Atdl4jWidget<E>
{
private final Logger logger = Logger.getLogger( AbstractAtdl4jWidget.class );
protected ParameterT parameter;
protected ControlT control;
protected ControlTypeConverter<E> controlConverter;
protected ParameterTypeConverter<?> parameterConverter;
private Atdl4jOptions atdl4jOptions;
Boolean nullValue = null; // undefined state
E lastNonNullStateControlValueRaw;
private boolean hiddenFieldForInputAndFilterData = false;
private StrategyPanelT parentStrategyPanel;
private Object parent;
public void init(ControlT aControl, ParameterT aParameter, Atdl4jOptions aAtdl4jOptions)
{
control = aControl;
parameter = aParameter;
setAtdl4jOptions( aAtdl4jOptions );
// -- This method can be overridden/implemented --
initPreCheck();
if ( parameter != null )
{
parameterConverter = (ParameterTypeConverter<?>) TypeConverterFactoryConfig.getTypeConverterFactory().createParameterTypeConverter( parameter );
}
// -- Pass parameterConverter (which may be null if parameter is null) --
controlConverter = (ControlTypeConverter<E>) TypeConverterFactoryConfig.getTypeConverterFactory().createControlTypeConverter( control, parameterConverter );
validateEnumPairs();
// -- This method can be overridden/implemented --
initPostCheck();
}
// gets the control name
public String getName()
{
return control.getID();
}
// -- Can be overridden --
protected void initPreCheck()
{
}
// -- Can be overridden --
protected void initPostCheck()
{
}
public void reinit()
{
// -- clear our "last value" state --
setLastNonNullStateControlValueRaw( null );
// -- check for Controls containing Parameter with constValue --
if ( applyConstValue() )
{
return; // -- return if constValue has been applied --
}
// -- reset what is displayed to the user --
processReinit( ControlHelper.getReinitValue( getControl(), getAtdl4jOptions() ) );
}
protected abstract void processReinit( Object aControlInitValue );
/**
* Should be invoked after Control's Widget has been fully established. Applies Parameter's constValue to the Control
* @return true if const value set
*/
private boolean applyConstValue()
{
if ( getParameter() != null )
{
Object tempConstValue = ParameterHelper.getConstValue( getParameter() );
if ( tempConstValue != null )
{
E tempControlValue = controlConverter.convertParameterValueToControlValue( tempConstValue, getControl() );
if ( tempControlValue != null )
{
setValue( tempControlValue );
processConstValueHasBeenSet();
return true;
}
else
{
throw new IllegalArgumentException( "Unable to convert constValue [" + tempConstValue + "] -- required when Parameter@constValue is non-null [Parameter: " + parameter.getName() + "]");
}
}
}
return false;
}
/**
* Should be invoked after Control's Widget has been fully established. Applies Parameter's constValue to the Control
*/
private void applyInitValue()
{
}
public void applyConstOrInitValues()
{
applyConstValue();
applyInitValue();
}
/**
* Will return null if isNullValue() is true, otherwise returns
* getControlValueRaw()
*
* @return
*/
public E getControlValue()
{
if ( isNullValue() )
{
return null;
}
else
{
return getControlValueRaw();
}
}
public Comparable<?> getControlValueAsComparable()
{
return controlConverter.convertControlValueToControlComparable( getControlValue() );
}
public String getParameterFixWireValue()
{
return parameter == null ? null : parameterConverter.convertParameterValueToFixWireValue( getParameterValue() );
}
public Comparable<?> getParameterValueAsComparable()
{
return parameter == null ? null : parameterConverter.convertParameterValueToParameterComparable( getParameterValue() );
}
/*
* This method handles string matching Atdl4jConstants.VALUE_NULL_INDICATOR
* and invoking setNullValue().
*/
public void setValueAsString(String aString)
{
if ( Atdl4jConstants.VALUE_NULL_INDICATOR.equals( aString ) )
{
setNullValue( Boolean.TRUE );
// -- note that this has no effect on the internal value which may have already been set --
}
else
// -- not null --
{
E tempValue = controlConverter.convertStringToControlValue( aString );
setValue( tempValue );
if ( ( tempValue == null ) && ( getNullValue() != null ) )
{
setNullValue( Boolean.TRUE );
}
else
{
setNullValue( Boolean.FALSE );
}
}
}
public Comparable<?> convertStringToControlComparable(String aString)
{
E tempControlValue = controlConverter.convertStringToControlValue( aString );
return controlConverter.convertControlValueToControlComparable( tempControlValue );
}
public Comparable<?> convertParameterStringToParameterComparable(String aParameterString)
{
// check if the control has an enum list
// then check if the parameter string is an enum value (as opposed to a raw FIX value)
String tempParameterString = (getListItems()==null||getEnumWireValue(aParameterString)==null) ?
aParameterString : getEnumWireValue(aParameterString);
if ( parameterConverter != null )
{
Object tempParameterValue = parameterConverter.convertParameterStringToParameterValue( tempParameterString );
return parameterConverter.convertParameterValueToParameterComparable( tempParameterValue );
}
else return null;
}
public ParameterT getParameter()
{
return parameter;
}
public boolean hasParameter()
{
return ( this.parameter != null );
}
public ControlT getControl()
{
return control;
}
public String getFIXValue()
{
StringFIXMessageBuilder builder = new StringFIXMessageBuilder();
builder.onStart();
getFIXValue( builder );
builder.onEnd();
return builder.getMessage();
}
public String getTooltip()
{
if ( control.getTooltip() != null )
return control.getTooltip();
else if ( parameter != null && parameter.getDescription() != null )
return parameter.getDescription();
return null;
}
public int getFIXType()
{
return Tag959Helper.toInteger( getParameter() );
}
public void getFIXValue(FIXMessageBuilder builder)
{
String value = getParameterFixWireValue();
if ( value != null )
{
if ( getParameter().getFixTag() != null
&& getParameter().getFixTag().intValue()!= Atdl4jConstants.TAG_NO_STRATEGY_PARAMETERS
&& getParameter().getFixTag().intValue()!= Atdl4jConstants.TAG_STRATEGY_PARAMETER_NAME
&& getParameter().getFixTag().intValue()!= Atdl4jConstants.TAG_STRATEGY_PARAMETER_TYPE
&& getParameter().getFixTag().intValue()!= Atdl4jConstants.TAG_STRATEGY_PARAMETER_VALUE)
{
builder.onField( getParameter().getFixTag().intValue(), value.toString() );
}
else
{
if ( getParameter().getName().startsWith( InputAndFilterData.FIX_DEFINED_FIELD_PREFIX ) )
{
// bypass Hidden "standard fields" (eg "FIX_OrderQty")
}
else
{
String name = getParameter().getName();
String type = Integer.toString( getFIXType() );
builder.onField( Atdl4jConstants.TAG_STRATEGY_PARAMETER_NAME, name );
builder.onField( Atdl4jConstants.TAG_STRATEGY_PARAMETER_TYPE, type );
builder.onField( Atdl4jConstants.TAG_STRATEGY_PARAMETER_VALUE, value.toString() );
}
}
}
}
// Helper method to validate that EnumPairs and ListItems match for
// the given Parameter and Control pair.
protected void validateEnumPairs()
{
if ( parameter != null )
{
List<EnumPairT> enumPairs = parameter.getEnumPair();
List<ListItemT> listItems = getListItems();
if ( control instanceof HiddenFieldT )
{
// don't need to validate in case of HiddenFieldT
}
else if ( control instanceof RadioButtonT || control instanceof CheckBoxT )
{
// validate checkedEnumRef and uncheckedEnumRef
}
else if ( listItems == null || listItems.size() == 0 )
{
if ( enumPairs != null && enumPairs.size() > 0 )
{
throw new IllegalArgumentException( "Parameter \"" + parameter.getName() + "\" has EnumPairs but Control \"" + control.getID()
+ "\" does not have ListItems." );
}
}
else if ( parameter.getEnumPair() != null )
{
if ( listItems.size() != enumPairs.size() )
throw new IllegalArgumentException( "Parameter \"" + parameter.getName() + "\" has " + enumPairs.size() + " EnumPairs but Control \""
+ control.getID() + "\" has " + listItems.size() + " ListItems." );
for ( ListItemT listItem : listItems )
{
boolean match = false;
for ( EnumPairT enumPair : enumPairs )
{
if ( listItem.getEnumID().equals( enumPair.getEnumID() ) )
{
match = true;
break;
}
}
if ( !match )
throw new IllegalArgumentException( "ListItem \"" + listItem.getEnumID() + "\" on Control \"" + control.getID()
+ "\" does not have a matching EnumPair on Parameter \"" + parameter.getName() + "\"." );
}
}
}
}
// Helper method to lookup a parameter string where the EnumID is matched
// across the ListItemTs and EnumPairTs
protected String getEnumWireValue(String enumID)
{
if ( parameter != null )
{
return ParameterHelper.getWireValueForEnumID( parameter, enumID );
// throw error?
}
return null;
}
// Helper method to lookup a parameter string where the EnumID is matched
// across the ListItemTs and EnumPairTs
protected String getParameterValueAsEnumWireValue()
{
if ( getControlValue() != null )
{
return getEnumWireValue( getControlValue().toString() );
}
else
{
return null;
}
}
// Helper method to convert MultipleValueChar / MultipleValueString Control
// values to ParameterValues
protected String getParameterValueAsMultipleValueString()
{
String value = "";
if ( getControlValue() != null )
{
String enumIDs = getControlValue().toString();
if ( enumIDs != null && parameter != null )
{
for ( String enumID : enumIDs.split( "\\s" ) )
{
if ( "".equals( value ) )
{
value += getEnumWireValue( enumID );
}
else
{
value += " " + getEnumWireValue( enumID );
}
}
}
}
return "".equals( value ) ? null : value;
}
// Helper method to get control ListItems
protected List<ListItemT> getListItems()
{
if ( control instanceof DropDownListT )
{
return ( (DropDownListT) control ).getListItem();
}
else if ( control instanceof EditableDropDownListT )
{
return ( (EditableDropDownListT) control ).getListItem();
}
else if ( control instanceof RadioButtonListT )
{
return ( (RadioButtonListT) control ).getListItem();
}
else if ( control instanceof CheckBoxListT )
{
return ( (CheckBoxListT) control ).getListItem();
}
else if ( control instanceof SingleSelectListT )
{
return ( (SingleSelectListT) control ).getListItem();
}
else if ( control instanceof MultiSelectListT )
{
return ( (MultiSelectListT) control ).getListItem();
}
else if ( control instanceof SliderT )
{
return ( (SliderT) control ).getListItem();
}
else
{
// TODO: this should maybe throw a runtime error???
// return an empty list
// return new Vector<ListItemT>();
return null;
}
}
/**
* @return the atdl4jOptions
*/
public Atdl4jOptions getAtdl4jOptions()
{
return this.atdl4jOptions;
}
/**
* @param aAtdl4jOptions
* the atdl4jOptions to set
*/
protected void setAtdl4jOptions(Atdl4jOptions aAtdl4jOptions)
{
this.atdl4jOptions = aAtdl4jOptions;
}
/**
* Note contains special logic to support returning false if: (
* getAtdl4jOptions().isTreatControlVisibleFalseAsNull() ) && ( ! isVisible()
* ) or ( ( getAtdl4jOptions().isTreatControlEnabledFalseAsNull() ) && ( !
* isEnabled() ) ) if those configs are set and nullValue is false.
*
* @return the nullValue
*/
public boolean isNullValue()
{
if ( getNullValue() != null )
{
// -- If we have it set, use it --
return getNullValue().booleanValue();
}
else
// -- our nullValue is in an undefined state --
{
// -- Special logic to treat non-visible and/or non-enabled as "null"
// if nullValue is false --
if ( getAtdl4jOptions() != null )
{
if (isVisible())
{
if (isControlExcludingLabelEnabled()){
return false;
} else if (getAtdl4jOptions().isTreatControlEnabledFalseAsNull())
{
return true;
}
} else if (getAtdl4jOptions().isTreatControlVisibleFalseAsNull())
{
return true;
}
}
// -- Treat getNullValue() == null as FALSE --
return false;
}
}
/**
* @return
*/
public Boolean getNullValue()
{
return this.nullValue;
}
/**
*
*/
abstract protected void processNullValueIndicatorChange(Boolean aOldNullValueInd, Boolean aNewNullValueInd);
/**
* @param aNullValue
* the nullValue to set
*/
public void setNullValue(Boolean aNullValue)
{
Boolean tempPreExistingNullValue = this.nullValue;
// -- Assign the value --
this.nullValue = aNullValue;
logger.debug( "setNullValue() control ID:" + getControl().getID() + " tempPreExistingNullValue: " + tempPreExistingNullValue + " aNullValue: "
+ aNullValue );
// -- Check to see if aNullValue provided is different than the
// pre-existing value --
if ( ( ( aNullValue != null ) && ( !aNullValue.equals( tempPreExistingNullValue ) ) )
|| ( ( tempPreExistingNullValue != null ) && ( !tempPreExistingNullValue.equals( aNullValue ) ) ) )
{
// -- "retain" the Control's last non-null raw value when changing to
// aNullValue of true --
if ( ( ( tempPreExistingNullValue == null ) || ( Boolean.FALSE.equals( tempPreExistingNullValue ) ) )
&& ( Boolean.TRUE.equals( aNullValue ) ) )
{
logger.debug( "setNullValue() control ID:" + getControl().getID() + " tempPreExistingNullValue: " + tempPreExistingNullValue
+ " aNullValue: " + aNullValue + " invoking setLastNonNullStateControlValueRaw( " + getControlValueRaw() + " )" );
setLastNonNullStateControlValueRaw( getControlValueRaw() );
}
// -- value has changed, notify --
processNullValueIndicatorChange( tempPreExistingNullValue, aNullValue );
// -- "restore" the Control's raw value if so configured when going
// from aNullValue of true to non-null --
if ( ( Boolean.FALSE.equals( aNullValue ) ) && ( getLastNonNullStateControlValueRaw() != null ) )
{
if ( getAtdl4jOptions().isRestoreLastNonNullStateControlValueBehavior() )
{
logger
.debug( "setNullValue() control ID:" + getControl().getID() + " tempPreExistingNullValue: " + tempPreExistingNullValue
+ " aNullValue: " + aNullValue + " invoking restoreLastNonNullStateControlValue( " + getLastNonNullStateControlValueRaw()
+ " )" );
restoreLastNonNullStateControlValue( getLastNonNullStateControlValueRaw() );
}
}
}
}
/**
* This method could be overridden for specific controls, if so desired.
*
* @param aLastNonNullStateControlValue
*/
protected void restoreLastNonNullStateControlValue(E aLastNonNullStateControlValue)
{
setValue( aLastNonNullStateControlValue );
}
/**
* @return the lastNonNullStateControlValueRaw
*/
public E getLastNonNullStateControlValueRaw()
{
return this.lastNonNullStateControlValueRaw;
}
/**
* @param aLastNonNullStateControlValueRaw
* the lastNonNullStateControlValueRaw to set
*/
protected void setLastNonNullStateControlValueRaw(E aLastNonNullStateControlValueRaw)
{
this.lastNonNullStateControlValueRaw = aLastNonNullStateControlValueRaw;
}
/**
* Used when pre-populating a control with its FIX message wire value
* For example: PercentageT with isMultiplyBy100() == true would have ".1234" on the wire for "12.34" displayed/stored by the control (for 12.34%).
* @param aFIXValue
*/
public void setFIXValue( String aFIXValue )
{
// -- Must use parameterConverter's convertToControlString (eg TextField's controlConverter is a StringConverter, not a DecimalConverter like the Parameter's would be) --
Object tempParameterValue = parameterConverter.convertFixWireValueToParameterValue( aFIXValue );
E tempValue = controlConverter.convertParameterValueToControlValue( tempParameterValue, getControl() );
if ( ( tempValue == null ) && ( getNullValue() != null ) )
{
logger.debug( "setFIXValue: " + aFIXValue + " Parameter value: " + tempParameterValue + " Control value: " + tempValue + ". Setting Control.nullValue=TRUE." );
setNullValue( Boolean.TRUE );
}
else
{
logger.debug( "setFIXValue: " + aFIXValue + " Parameter value: " + tempParameterValue + " Control value: " + tempValue );
setNullValue( Boolean.FALSE );
}
setValue( tempValue );
}
/**
* Default implementation. Can be overridden if so desired.
*/
public void processConstValueHasBeenSet()
{
setControlExcludingLabelEnabled( false );
}
public Object getParameterValue()
{
E tempControlValue = getControlValue();
return controlConverter.convertControlValueToParameterValue( tempControlValue );
}
/**
* @return the hiddenFieldForInputAndFilterData
*/
public boolean isHiddenFieldForInputAndFilterData()
{
return this.hiddenFieldForInputAndFilterData;
}
/**
* @param aHiddenFieldForInputAndFilterData the hiddenFieldForInputAndFilterData to set
*/
public void setHiddenFieldForInputAndFilterData(boolean aHiddenFieldForInputAndFilterData)
{
this.hiddenFieldForInputAndFilterData = aHiddenFieldForInputAndFilterData;
}
/* Overriden to delegate to Atdl4jWidget's ControlT data member. (note Atdl4jWidget map may be shallow copied resulting in new identity for Atdl4jWidget objects)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object aObj)
{
if ( ( getControl() != null ) &&
( aObj instanceof Atdl4jWidget<?> ) )
{
return getControl().equals( ((Atdl4jWidget<?>) aObj).getControl() );
}
else
{
return super.equals( aObj );
}
}
/* Overriden to delegate to Atdl4jWidget's ControlT data member. (note Atdl4jWidget map may be shallow copied resulting in new identity for Atdl4jWidget objects)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
if ( getControl() != null )
{
return getControl().hashCode();
}
else
{
return super.hashCode();
}
}
/**
* @return the parentStrategyPanel
*/
public StrategyPanelT getParentStrategyPanel()
{
return this.parentStrategyPanel;
}
/**
* @param aParentStrategyPanel the parentStrategyPanel to set
*/
public void setParentStrategyPanel(StrategyPanelT aParentStrategyPanel)
{
this.parentStrategyPanel = aParentStrategyPanel;
}
/**
* @return the parent
*/
public Object getParent()
{
return this.parent;
}
/**
* @param aParent the parent to set
*/
public void setParent(Object aParent)
{
this.parent = aParent;
}
}