package tcg.scada.da;
import java.util.ArrayList;
import tcg.common.LoggerManager;
import tcg.common.util.ExpressionParser;
import tcg.scada.cos.CosDpValueTypeEnum;
/**
* Implementation of output datapoint.
*
* <p>
* Output datapoint is a dummy datapoint structure. No operation is supported
* other than set and get.
* </p>
*
* <p>
* Expected behaviour for output datapoint (behave like dummy datapoint):
* <ul>
* <li>Source value: not applicable. always default value</li>
* <li>Source quality: not applicable. (default = GoodQuality)</li>
* <li>Source timestamp: not applicable. (default = 0)</li>
* <li>Output value: not applicable.</li>
* <li>Output quality: not applicable.</li>
* <li>Output timestamp: not applicable.</li>
* </ul>
* </p>
*
* @author Yoga
*
*/
public class OutputDataPoint extends DataPoint
{
// launching condition for control point
// protected String lccExpression = "";
protected ExpressionParser lccParser = null;
protected ArrayList<IDataPoint> lccParams = null;
// return condition for control point
// protected String rccExpression = "";
protected ExpressionParser rccParser = null;
protected ArrayList<IDataPoint> rccParams = null;
/**
* Default ctor.
*
* @param inDataType
* - the internal data type
*/
public OutputDataPoint(CosDpValueTypeEnum inDataType)
{
// output point is only supported for boolean/number data type
if (inDataType.value() != CosDpValueTypeEnum._TypeNumber
&& inDataType.value() != CosDpValueTypeEnum._TypeBoolean)
{
// force it to be number type
inDataType = CosDpValueTypeEnum.TypeNumber;
}
super._setDataType(inDataType);
// override the logger
logger = LoggerManager.getLogger(this.getClass().getName());
}
@Override
public EDataPointType getType()
{
return EDataPointType.TYPE_OUTPUT;
}
@Override
public synchronized boolean setReturnCondition(String inExpression,
DataPointList inDpList)
{
// validation: inExpression
if (inExpression == null || inExpression.isEmpty())
{
return false;
}
// validation: inDpList
// none
// first of all get the return type
Class<?> type = boolean.class;
// parse the expression. this must be done after all datapoints have
// been created
// otherwise, invalid/non-existent datapoints will be just marked as 0.
ArrayList<IDataPoint> params = new ArrayList<IDataPoint>();
ArrayList<String> varnames = new ArrayList<String>();
ArrayList<Class<?>> vartypes = new ArrayList<Class<?>>();
ArrayList<Object> varvalues = new ArrayList<Object>();
// parse the expression
String parsedExpression = _parseExpression(inDpList, inExpression,
params, varnames, vartypes, varvalues);
// create the parser
rccParser = new ExpressionParser(parsedExpression, type);
// create all the variables
for (int i = 0; i < varnames.size(); i++)
{
rccParser.createVariable(varnames.get(i), vartypes.get(i),
varvalues.get(i));
}
// copy the list of datapoint component
rccParams = params;
// try to evaluate
try
{
Object result = rccParser.evaluate();
if (result == null)
{
return false;
}
}
catch (Exception ex)
{
logger.error("Can not set RCC expression: " + ex.getMessage());
return false;
}
// successful
return true;
}
@Override
public synchronized boolean checkReturnCondition()
{
// validation: RCC parser is never set
if (rccParser == null)
{
return false;
}
// check for invalid expression
if (!rccParser.isValid())
{
// it has been parsed and found invalid. prevent re-parsing
logger.error("Invalid RCC expression. "
+ "Check the first time this happens for error.");
return false;
}
// update the value of expression parameters
IDataPoint datapoint = null;
Object value = null;
for (int i = 0; i < rccParams.size(); i++)
{
datapoint = rccParams.get(i);
if (datapoint == null)
{
logger.trace("RCC parameter : UNKNOWN");
value = Integer.valueOf(0); // default value
}
else
{
logger.trace("RCC parameter : " + datapoint.getName());
// calculate the parameter value
value = convCosDpValueUnion2Object(datapoint.getValue());
}
// set the parameter
rccParser.set(i, value);
// verbose
logger.trace("RCC parameter value : " + value.toString());
}
// evaluate the expression value
Boolean status = null;
try
{
status = (Boolean) rccParser.evaluate();
}
catch (Exception ex)
{
logger.warn("Can not evaluate RCC expression. Exception: "
+ ex.toString());
}
// return value
if (status == null)
{
return false;
}
else
{
return status.booleanValue();
}
}
@Override
public synchronized boolean setLaunchCondition(String inExpression,
DataPointList inDpList)
{
// validation: inExpression
if (inExpression == null || inExpression.isEmpty())
{
return false;
}
// validation: inDpList
// none
// first of all get the return type
Class<?> type = boolean.class;
// parse the expression. this must be done after all datapoints have
// been created
// otherwise, invalid/non-existent datapoints will be just marked as 0.
ArrayList<IDataPoint> params = new ArrayList<IDataPoint>();
ArrayList<String> varnames = new ArrayList<String>();
ArrayList<Class<?>> vartypes = new ArrayList<Class<?>>();
ArrayList<Object> varvalues = new ArrayList<Object>();
// parse the expression
String parsedExpression = _parseExpression(inDpList, inExpression,
params, varnames, vartypes, varvalues);
// create the parser
lccParser = new ExpressionParser(parsedExpression, type);
// create all the variables
for (int i = 0; i < varnames.size(); i++)
{
lccParser.createVariable(varnames.get(i), vartypes.get(i),
varvalues.get(i));
}
// copy the list of datapoint component
lccParams = params;
// try to evaluate
try
{
Object result = lccParser.evaluate();
if (result == null)
{
return false;
}
}
catch (Exception ex)
{
logger.error("Can not set LCC expression: " + ex.getMessage());
return false;
}
// successful
return true;
}
@Override
public synchronized boolean checkLaunchCondition()
{
// validation: LCC parser is never set
if (lccParser == null)
{
return false;
}
// check for invalid expression
if (!lccParser.isValid())
{
// it has been parsed and found invalid. prevent re-parsing
logger.error("Invalid LCC expression. "
+ "Check the first time this happens for error.");
return false;
}
// update the value of expression parameters
IDataPoint datapoint = null;
Object value = null;
for (int i = 0; i < lccParams.size(); i++)
{
datapoint = lccParams.get(i);
if (datapoint == null)
{
logger.trace("LCC parameter : UNKNOWN");
value = Integer.valueOf(0); // default value
}
else
{
logger.trace("LCC parameter : " + datapoint.getName());
// calculate the parameter value
value = convCosDpValueUnion2Object(datapoint.getValue());
}
// set the parameter
lccParser.set(i, value);
// verbose
logger.trace("LCC parameter value : " + value.toString());
}
// evaluate the expression value
Boolean status = null;
try
{
status = (Boolean) lccParser.evaluate();
}
catch (Exception ex)
{
logger.warn("Can not evaluate LCC expression. Exception: "
+ ex.toString());
}
// return value
if (status == null)
{
return false;
}
else
{
return status.booleanValue();
}
}
}