package org.sana.android.procedure.branching;
import org.sana.BuildConfig;
import org.sana.android.procedure.MultiSelectElement;
import org.sana.android.procedure.ProcedureElement;
import org.sana.android.procedure.ProcedureParseException;
import org.sana.android.procedure.ProcedureElement.ElementType;
import android.util.Log;
/**
* The Criterion class is a data representation of the XML
* <p/>
* <Criteria type="" elementId="" value=""/>
* <p/>
* It holds a reference to the element elementId refers to so that it can
* determine user responses. The three Criterion Types (EQUALS, GREATER, LESS)
* are logically-complete, since a Criterion object will always sit inside a
* Criteria object, which can perform arbitrary boolean logic on it.
*/
public class Criterion {
public static enum CriterionType {
EQUALS, GREATER, LESS
}
private static final String TAG = "Criterion";
private CriterionType criterionType;
private ProcedureElement element;
private String value;
/**
* A new Criterion object
* @param critType The type of Criterion
* @param elmt The source element in the Procedure
* @param val The <code>value</code> attribute for this Criterion
* @throws ProcedureParseException
*/
public Criterion(CriterionType critType, ProcedureElement elmt, String val)
throws ProcedureParseException
{
this.criterionType = critType;
this.element = elmt;
this.value = val;
if (elmt == null)
throw new ProcedureParseException("Null element");
if ((critType == CriterionType.GREATER) ||
(critType == CriterionType.LESS))
{
try {
Double.parseDouble(val);
} catch (NumberFormatException e) {
throw new ProcedureParseException("Cannot compare non-numeric "
+"value. Cannot create criterion for element "
+ elmt.getId());
}
}
}
/**
* Checks if the given Criterion is met, given user responses.
*
* For a Criterion based on a Multi-Select element, if any of the choices
* evaluates as true, then the Criterion is met.
*
* For blank (unanswered, blank default) elements, criterionMet evaluates
* as true.
*/
public boolean criterionMet() {
// lookup what the user selected
String userVal = "";
try {
userVal = element.getAnswer();
} catch (NullPointerException e) {
// play it safe and show the page
return false;
}
// check if it is empty
if ((userVal == "") || (userVal== null)) {
// empty user response, lets play it safe and show the page
return false;
}
// special case MULTI-SELECT
if (element.getType() == ElementType.MULTI_SELECT) {
// We (arbitrarily) handle MultiSelect by seeing if
// ANY selection in the "answer" matches "val"
// if so, then it evaluates as true
String[] vals = userVal.split(MultiSelectElement.TOKEN_DELIMITER);
for (String s : vals) {
if (criterionMetHelper(s))
return true;
}
return false;
} else {
// test the user's answer against the criterion
return criterionMetHelper(userVal);
}
}
private boolean criterionMetHelper(String userVal) {
boolean result = false;
switch(criterionType) {
case EQUALS:
if (value.compareToIgnoreCase(userVal) == 0) {
result = true;
}
break;
case GREATER:
try {
if (Double.parseDouble(userVal) > Double.parseDouble(value))
result = true;
// show the page if we can't parse
} catch (NumberFormatException e) {return true;}
break;
case LESS:
try {
if (Double.parseDouble(userVal) < Double.parseDouble(value))
result = true;
// show the page if we can't parse
} catch (NumberFormatException e) {return true;}
break;
}
/*
if(BuildConfig.DEBUG)
Log.d(TAG, "criterionMetHelper(): " + criterionType
+ "(Criterion,User Value): (" +value +"," + userVal + ") "
+ " result = " + result);
*/
return result;
}
}