/*
* file: GenericCriteria.java
* author: Jon Iles
* copyright: (c) Packwood Software 2006
* date: 30/10/2006
*/
/*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
package net.sf.mpxj;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import net.sf.mpxj.common.DateHelper;
/**
* This class represents the criteria used as part of an evaluation.
*/
public class GenericCriteria
{
/**
* Constructor.
*
* @param properties project properties
*/
public GenericCriteria(ProjectProperties properties)
{
m_properties = properties;
}
/**
* Sets the LHS of the expression.
*
* @param value LHS value
*/
public void setLeftValue(FieldType value)
{
m_leftValue = value;
}
/**
* Retrieves the LHS of the expression.
*
* @return LHS value
*/
public FieldType getLeftValue()
{
return (m_leftValue);
}
/**
* Retrieve the operator used in the test.
*
* @return test operator
*/
public TestOperator getOperator()
{
return m_operator;
}
/**
* Set the operator used in the test.
*
* @param operator test operator
*/
public void setOperator(TestOperator operator)
{
m_operator = operator;
}
/**
* Add the value to list of values to be used as part of the
* evaluation of this indicator.
*
* @param index position in the list
* @param value evaluation value
*/
public void setRightValue(int index, Object value)
{
m_definedRightValues[index] = value;
if (value instanceof FieldType)
{
m_symbolicValues = true;
}
else
{
if (value instanceof Duration)
{
if (((Duration) value).getUnits() != TimeUnit.HOURS)
{
value = ((Duration) value).convertUnits(TimeUnit.HOURS, m_properties);
}
}
}
m_workingRightValues[index] = value;
}
/**
* Retrieve the first value.
*
* @param index position in the list
* @return first value
*/
public Object getValue(int index)
{
return (m_definedRightValues[index]);
}
/**
* Evaluate the criteria and return a boolean result.
*
* @param container field container
* @param promptValues responses to prompts
* @return boolean flag
*/
public boolean evaluate(FieldContainer container, Map<GenericCriteriaPrompt, Object> promptValues)
{
//
// Retrieve the LHS value
//
FieldType field = m_leftValue;
Object lhs;
if (field == null)
{
lhs = null;
}
else
{
lhs = container.getCurrentValue(field);
switch (field.getDataType())
{
case DATE:
{
if (lhs != null)
{
lhs = DateHelper.getDayStartDate((Date) lhs);
}
break;
}
case DURATION:
{
if (lhs != null)
{
Duration dur = (Duration) lhs;
lhs = dur.convertUnits(TimeUnit.HOURS, m_properties);
}
else
{
lhs = Duration.getInstance(0, TimeUnit.HOURS);
}
break;
}
case STRING:
{
lhs = lhs == null ? "" : lhs;
break;
}
default:
{
break;
}
}
}
//
// Retrieve the RHS values
//
Object[] rhs;
if (m_symbolicValues == true)
{
rhs = processSymbolicValues(m_workingRightValues, container, promptValues);
}
else
{
rhs = m_workingRightValues;
}
//
// Evaluate
//
boolean result;
switch (m_operator)
{
case AND:
case OR:
{
result = evaluateLogicalOperator(container, promptValues);
break;
}
default:
{
result = m_operator.evaluate(lhs, rhs);
break;
}
}
return result;
}
/**
* Evalutes AND and OR operators.
*
* @param container data context
* @param promptValues responses to prompts
* @return operator result
*/
private boolean evaluateLogicalOperator(FieldContainer container, Map<GenericCriteriaPrompt, Object> promptValues)
{
boolean result = false;
if (m_criteriaList.size() == 0)
{
result = true;
}
else
{
for (GenericCriteria criteria : m_criteriaList)
{
result = criteria.evaluate(container, promptValues);
if ((m_operator == TestOperator.AND && !result) || (m_operator == TestOperator.OR && result))
{
break;
}
}
}
return result;
}
/**
* This method is called to create a new list of values, converting from
* any symbolic values (represented by FieldType instances) to actual
* values retrieved from a Task or Resource instance.
*
* @param oldValues list of old values containing symbolic items
* @param container Task or Resource instance
* @param promptValues response to prompts
* @return new list of actual values
*/
private Object[] processSymbolicValues(Object[] oldValues, FieldContainer container, Map<GenericCriteriaPrompt, Object> promptValues)
{
Object[] newValues = new Object[2];
for (int loop = 0; loop < oldValues.length; loop++)
{
Object value = oldValues[loop];
if (value == null)
{
continue;
}
if (value instanceof FieldType)
{
FieldType type = (FieldType) value;
value = container.getCachedValue(type);
switch (type.getDataType())
{
case DATE:
{
if (value != null)
{
value = DateHelper.getDayStartDate((Date) value);
}
break;
}
case DURATION:
{
if (value != null && ((Duration) value).getUnits() != TimeUnit.HOURS)
{
value = ((Duration) value).convertUnits(TimeUnit.HOURS, m_properties);
}
else
{
value = Duration.getInstance(0, TimeUnit.HOURS);
}
break;
}
case STRING:
{
value = value == null ? "" : value;
break;
}
default:
{
break;
}
}
}
else
{
if (value instanceof GenericCriteriaPrompt && promptValues != null)
{
GenericCriteriaPrompt prompt = (GenericCriteriaPrompt) value;
value = promptValues.get(prompt);
}
}
newValues[loop] = value;
}
return (newValues);
}
/**
* Retrieves the list of child criteria associated with the current criteria.
*
* @return list of criteria
*/
public List<GenericCriteria> getCriteriaList()
{
return m_criteriaList;
}
/**
* Adds a an item to the list of child criteria.
*
* @param criteria criteria item to add
*/
public void addCriteria(GenericCriteria criteria)
{
m_criteriaList.add(criteria);
}
/**
* {@inheritDoc}
*/
@Override public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("(");
switch (m_operator)
{
case AND:
case OR:
{
int index = 0;
for (GenericCriteria c : m_criteriaList)
{
sb.append(c);
++index;
if (index < m_criteriaList.size())
{
sb.append(" ");
sb.append(m_operator);
sb.append(" ");
}
}
break;
}
default:
{
sb.append(m_leftValue);
sb.append(" ");
sb.append(m_operator);
sb.append(" ");
sb.append(m_definedRightValues[0]);
if (m_definedRightValues[1] != null)
{
sb.append(",");
sb.append(m_definedRightValues[1]);
}
}
}
sb.append(")");
return (sb.toString());
}
private ProjectProperties m_properties;
private FieldType m_leftValue;
private TestOperator m_operator;
private Object[] m_definedRightValues = new Object[2];
private Object[] m_workingRightValues = new Object[2];
private boolean m_symbolicValues;
private List<GenericCriteria> m_criteriaList = new LinkedList<GenericCriteria>();
}