use of org.akaza.openclinica.exception.ScoreException in project OpenClinica by OpenClinica.
the class ScoreCalculator method redoCalculations.
/**
* Re-do calculations if funcs include changed item(s) and funcs are not
* included in the current section. If calculation can not sucessfully redo,
* old value will be erased and "<erased>" will be saved in database. <br>
* The parameter 'itemdata' might be overwritten.
*
* @param itemGroupSizes
* @param items
* @param itemdata
* @param oldItemdata
* @param updatedData
* @param sectionId
* @return ArrayList<String> which records left_item_text of items who
* failed to be updated into database.
*/
public ArrayList<String> redoCalculations(HashMap<String, ItemBean> items, HashMap<String, String> itemdata, TreeSet<String> changedItems, HashMap<Integer, TreeSet<Integer>> itemOrdinals, int sectionId) {
ArrayList<String> updateFailedItems = new ArrayList<String>();
if (itemdata == null) {
logger.error("In ScoreCalculator redoCalculations(), itemdata is empty!");
errors.add("In ScoreCalculator redoCalculations(), 'itemdata' map is empty!");
return updateFailedItems;
}
if (changedItems == null) {
logger.error("In ScoreCalculator redoCalculations(), 'changeItems' set is empty!");
errors.add("In ScoreCalculator redoCalculations(), 'changeItems' set is empty!");
return updateFailedItems;
}
ItemFormMetadataDAO ifmdao = new ItemFormMetadataDAO(sm.getDataSource());
ItemDAO idao = new ItemDAO(sm.getDataSource());
ItemDataDAO iddao = new ItemDataDAO(sm.getDataSource());
NumberFormat nf = NumberFormat.getInstance();
Parser parser = new Parser(items, itemdata);
try {
// for calculation type
List<ItemFormMetadataBean> derivedItemList = ifmdao.findAllByCRFVersionIdAndResponseTypeId(ecb.getCRFVersionId(), ResponseType.CALCULATION.getId());
if (derivedItemList.size() > 0) {
Collections.sort(derivedItemList);
for (ItemFormMetadataBean ifmb : derivedItemList) {
if (ifmb.getSectionId() != sectionId) {
ItemBean ib = (ItemBean) idao.findByPK(ifmb.getItemId());
ResponseOptionBean rob = (ResponseOptionBean) ifmb.getResponseSet().getOptions().get(0);
int groupsize = 1;
if (itemOrdinals.containsKey(ib.getId())) {
groupsize = itemOrdinals.get(ib.getId()).size();
}
String value = "";
ArrayList<ScoreToken> parsedExp = new ArrayList<ScoreToken>();
for (int i = 0; i < groupsize; ++i) {
ItemDataBean idb = iddao.findByItemIdAndEventCRFIdAndOrdinal(ifmb.getItemId(), ecb.getId(), i + 1);
// is there any changed item
Parser p = new Parser(items, itemdata);
parsedExp = parser.parseScoreTokens(rob.getValue());
if (p.isChanged(changedItems, parsedExp)) {
StringBuffer err = new StringBuffer();
parsedExp = parser.assignVariables(parsedExp, i + 1);
// before, set "<erased>"
if (parser.getErrors().length() > 0) {
err.append(parser.getErrors());
if (idb.isActive()) {
idb.setValue("<erased>");
idb.setStatus(Status.UNAVAILABLE);
idb = (ItemDataBean) iddao.update(idb);
if (!idb.isActive()) {
String key = i + 1 > 1 ? ifmb.getLeftItemText() + "_" + (i + 1) : ifmb.getLeftItemText();
updateFailedItems.add(key);
}
}
parser.setErrors(new StringBuffer());
} else // otherwise do calculation
{
try {
value = ScoreUtil.eval(parsedExp);
} catch (ScoreException se) {
logger.error(se.getMessage());
}
String exp = rob.getValue();
exp = exp.replace("##", ",");
if (writeToDB(ib, ifmb, idb, exp, value, err)) {
changedItems.add(ib.getName());
itemdata.put(ib.getId() + "_" + (i + 1), idb.getValue());
} else {
String key = i + 1 > 1 ? ifmb.getLeftItemText() + "_" + (i + 1) : ifmb.getLeftItemText();
updateFailedItems.add(key);
}
}
if (err.length() > 0) {
String key = i + 1 > 1 ? ifmb.getLeftItemText() + "_" + (i + 1) : ifmb.getLeftItemText();
errors.add("Item " + key + " contains calculation errors: " + err.toString());
}
}
}
}
}
}
List<ItemFormMetadataBean> itemList = ifmdao.findAllByCRFVersionIdAndResponseTypeId(ecb.getCRFVersionId(), ResponseType.GROUP_CALCULATION.getId());
if (itemList.size() > 0) {
Collections.sort(itemList);
for (ItemFormMetadataBean ifmb : itemList) {
if (ifmb.getSectionId() != sectionId) {
ItemBean ib = (ItemBean) idao.findByPK(ifmb.getItemId());
ResponseOptionBean rob = (ResponseOptionBean) ifmb.getResponseSet().getOptions().get(0);
String value = "";
Parser p = new Parser(items, itemdata);
ArrayList<ScoreToken> parsedExp = parser.parseScoreTokens(rob.getValue());
if (p.isChanged(changedItems, parsedExp)) {
StringBuffer err = new StringBuffer();
parser.setErrors(err);
parsedExp = parser.assignVariables(parsedExp, itemOrdinals);
ItemDataBean idb = iddao.findByItemIdAndEventCRFIdAndOrdinal(ifmb.getItemId(), ecb.getId(), 1);
if (parser.getErrors().length() > 0) {
err.append(parser.getErrors());
if (idb.isActive()) {
idb.setValue("<erased>");
idb.setStatus(Status.UNAVAILABLE);
idb = (ItemDataBean) iddao.update(idb);
if (!idb.isActive()) {
updateFailedItems.add(ifmb.getLeftItemText());
}
}
} else {
try {
value = ScoreUtil.eval(parsedExp);
} catch (ScoreException se) {
logger.error(se.getMessage());
}
String exp = rob.getValue();
exp = exp.replace("##", ",");
if (writeToDB(ib, ifmb, idb, exp, value, err)) {
changedItems.add(ib.getName());
itemdata.put(ib.getId() + "_" + idb.getOrdinal(), idb.getValue());
} else {
updateFailedItems.add(ifmb.getLeftItemText());
}
}
if (err.length() > 0) {
errors.add("Item " + ifmb.getLeftItemText() + " contains calculation errors: " + err.toString());
}
}
}
}
}
} catch (OpenClinicaException e) {
logger.error(e.getMessage());
}
return updateFailedItems;
}
use of org.akaza.openclinica.exception.ScoreException in project OpenClinica by OpenClinica.
the class ScoreUtil method eval.
/**
* Evaluation math expression which might contain functions.
* <p>
* Some pre-conditions:
* <ul>
* <li>Supported operators include only '+', '-', '*', '/'
* <li>Math expression should pass ScoreValidator before evaluation.
* </ul>
*
* @param expression
* @return String
*/
public static String eval(ArrayList<ScoreToken> expression) throws ScoreException {
if (expression == null || expression.size() < 1) {
return "";
}
ScoreToken token = new ScoreToken();
ArrayList<ScoreToken> finalexp = new ArrayList<ScoreToken>();
String value = "";
Info info = new Info();
info.pos = 0;
info.level = 0;
boolean couldBeSign = true;
while (info.pos < expression.size()) {
ScoreToken t = new ScoreToken();
t = expression.get(info.pos);
char c = t.getSymbol();
// ignore spaces
if (c == ' ') {
// do nothing
} else if (c == ScoreSymbol.ARITHMETIC_OPERATOR_SYMBOL) {
if (couldBeSign & isSign(t.getName())) {
if (token.getName().length() > 0) {
logger.info("Wrong at operator " + t.getName() + " at position " + info.pos);
throw new ScoreException(t.getName() + " at position " + info.pos + " is invalid.", "1");
} else {
token.setName(t.getName());
token.setSymbol(t.getSymbol());
}
couldBeSign = false;
} else {
if (token.getName().length() > 0) {
finalexp.add(token);
token = new ScoreToken();
}
finalexp.add(t);
couldBeSign = true;
}
} else if (c == '(') {
couldBeSign = true;
String sign = "";
String tokenname = token.getName();
if (tokenname.length() > 0 && isSign(tokenname.charAt(0))) {
sign = tokenname.charAt(0) + "";
tokenname = tokenname.substring(1);
}
String funcname = getFunctionName(tokenname);
if (funcname != null && !funcname.equalsIgnoreCase("getexternalvalue") && !funcname.equalsIgnoreCase(FUNCTION_PACKAGE + "getexternalvalue")) {
try {
token.setName(sign + evalFunc(expression, info, (Function) Class.forName(funcname).newInstance()));
token.setSymbol(ScoreSymbol.TERM_SYMBOL);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
finalexp.add(token);
token = new ScoreToken();
couldBeSign = false;
} else {
info.level++;
if (token.getName().length() > 0) {
finalexp.add(token);
}
token = new ScoreToken();
finalexp.add(t);
}
} else if (c == ')') {
couldBeSign = false;
if (token.getName().length() > 0) {
finalexp.add(token);
}
token = new ScoreToken();
finalexp.add(t);
info.level--;
} else // problem.
if (c == ',') {
token = new ScoreToken();
throw new ScoreException("Found unexpected character , when doing evaluation", "2");
} else {
couldBeSign = false;
if (isSign(token.getName())) {
token.setName(token.getName() + t.getName());
token.setSymbol(ScoreSymbol.TERM_SYMBOL);
} else {
token.setName(t.getName());
token.setSymbol(t.getSymbol());
}
}
info.pos++;
}
if (info.level != 0) {
// !!!!!
logger.info("expression invalid, unpaired parentheses.");
throw new ScoreException("Found unpaired parentheses when doing evaluation", "3");
}
// For example, to expression 2+4, we must do so.
if (token.getName().length() > 0) {
finalexp.add(token);
}
if (finalexp != null && finalexp.size() > 0) {
if (finalexp.size() == 1) {
value = finalexp.get(0).getName();
} else {
value = evalSimple(createPostfix(finalexp));
}
}
return "" + value;
}
use of org.akaza.openclinica.exception.ScoreException in project OpenClinica by OpenClinica.
the class ScoreUtil method evalFunc.
/**
* Evaluate a function which might contain arithmetic expressions, and
* return result as a String.
* <p>
* If an item can not be found in the eventCRF, it will be treated as empty.
* If empty items exist in a function, the result will be empty.
*
* @param contents
* @param info
* @param function
* @return
*/
public static String evalFunc(ArrayList<ScoreToken> contents, Info info, Function function) throws ScoreException {
int originalLevel = info.level;
info.pos++;
info.level++;
ScoreToken token = new ScoreToken();
// currArg is in fact representing the current argument.
ArrayList<ScoreToken> currArg = new ArrayList<ScoreToken>();
boolean couldBeSign = true;
while (info.pos < contents.size()) {
ScoreToken scoretoken = contents.get(info.pos);
char c = scoretoken.getSymbol();
if (c == ')') {
couldBeSign = false;
info.level--;
// end of the function, marked by the equal level
if (info.level == originalLevel) {
if (token.getName().length() > 0) {
currArg.add(token);
}
String t = evalArgument(currArg);
if (t != null && t.length() > 0) {
function.addArgument(t);
} else {
// error message has been handled in evalArgument()
return "";
}
token = new ScoreToken();
break;
} else {
// argument
if (token.getName().length() > 0) {
currArg.add(token);
}
currArg.add(scoretoken);
}
token = new ScoreToken();
} else if (c == '(') {
couldBeSign = true;
String sign = "";
String tokenname = token.getName();
if (tokenname.length() > 0 && isSign(tokenname.charAt(0))) {
sign = tokenname.charAt(0) + "";
tokenname = tokenname.substring(1);
}
// it is either the start of a function or an expression
String funcname = getFunctionName(tokenname);
if (funcname != null) {
// store in the current argument
try {
token.setName(sign + evalFunc(contents, info, (Function) Class.forName(funcname).newInstance()));
token.setSymbol(ScoreSymbol.TERM_SYMBOL);
currArg.add(token);
couldBeSign = false;
} catch (InstantiationException e) {
e.printStackTrace();
return "";
} catch (ClassNotFoundException e) {
e.printStackTrace();
return "";
} catch (IllegalAccessException e) {
e.printStackTrace();
return "";
}
} else // if it is the start of an expression
{
info.level++;
if (token.getName().length() > 0) {
currArg.add(token);
}
currArg.add(scoretoken);
}
token = new ScoreToken();
} else // end of an argument
if (c == ',') {
couldBeSign = true;
if (token.getName().length() > 0) {
currArg.add(token);
}
// compute the argument
String t = evalArgument(currArg);
if (t != null && t.length() > 0) {
function.addArgument(t);
} else {
return "";
}
token = new ScoreToken();
// reset the argument for next one
currArg = new ArrayList<ScoreToken>();
} else // else if(isOperator(c)){
if (c == ScoreSymbol.ARITHMETIC_OPERATOR_SYMBOL) {
if (couldBeSign && isSign(scoretoken.getName())) {
if (token.getName().length() > 0) {
throw new ScoreException(scoretoken.getName() + " at position " + info.pos + " is invalid.", "1");
} else {
// token = scoretoken;
token.setName(scoretoken.getName());
token.setSymbol(scoretoken.getSymbol());
}
couldBeSign = false;
} else {
if (token.getName().length() > 0) {
currArg.add(token);
}
token = new ScoreToken();
currArg.add(scoretoken);
couldBeSign = true;
}
} else {
couldBeSign = false;
if (isSign(token.getName())) {
token.setName(token.getName() + scoretoken.getName());
token.setSymbol(ScoreSymbol.TERM_SYMBOL);
} else {
if (c != ' ') {
// token = scoretoken;
token.setName(scoretoken.getName());
token.setSymbol(scoretoken.getSymbol());
}
}
}
info.pos++;
}
function.execute();
if (function.getErrors().size() > 0) {
String errors = new String();
HashMap<Integer, String> es = function.getErrors();
for (int i = 0; i < es.size(); ++i) {
errors += es.get(Integer.valueOf(i));
}
throw new ScoreException(errors, "4");
}
return function.getValue();
}
use of org.akaza.openclinica.exception.ScoreException in project OpenClinica by OpenClinica.
the class ScoreCalculator method doCalculation.
/*
* Perform all calculations in a CRFVersion. The parameter 'itemdata' might
* be overwritten.
*
* @param calcItemGroupSizes @param items @param itemdata @param
* itemGroupSizes @param databaseErrors @return ArrayList<String> which
* records left_item_text of items who failed to be updated into database.
*
*
* //this method has not been fully tested yet
*
*
* public ArrayList<String> doCalculations( HashMap<String,ItemBean>
* items, HashMap<String,String> itemdata, HashMap<Integer,TreeSet<Integer>>
* itemOrdinals) { ArrayList<String> updateFailedItems = new ArrayList<String>();
* if(itemdata==null) { //here, actually only record errors but doesn't
* return errors. logger.error("In scoreCalculator doCalculations(), items
* are empty!"); errors.add("Calculation cannot be started because needed
* items are empty!"); return updateFailedItems; } ItemFormMetadataDAO
* ifmdao = new ItemFormMetadataDAO(sm.getDataSource()); ItemDAO idao = new
* ItemDAO(sm.getDataSource()); ItemDataDAO iddao = new
* ItemDataDAO(sm.getDataSource());
*
* NumberFormat nf = NumberFormat.getInstance(); Parser parser = new
* Parser(items,itemdata); try { //for calculation type List<ItemFormMetadataBean>
* derivedItemList = ifmdao.findAllByCRFVersionIdAndResponseTypeId(
* ecb.getCRFVersionId(), ResponseType.CALCULATION.getId());
* if(derivedItemList.size()>0) { Collections.sort(derivedItemList); for
* (ItemFormMetadataBean ifmb: derivedItemList) { ItemBean ib =
* (ItemBean)idao.findByPK(ifmb.getItemId()); ResponseOptionBean rob =
* (ResponseOptionBean)ifmb.getResponseSet().getOptions().get(0); //YW,
* 1-16-2008, << enable: 1. evaluate combination of expression and
* functions 2. scoring for group items. //int groupsize =
* iddao.getMaxOrdinalForGroup(ecb,
* (SectionBean)sdao.findByPK(ifmb.getSectionId()), //
* (ItemGroupBean)igdao.findByName(ifmb.getGroupLabel())); int groupsize =
* 1; if(itemOrdinals.containsKey(ib.getId())) { groupsize =
* (itemOrdinals.get(ib.getId())).size(); } String value = ""; String
* parsedExp = ""; for(int i=0; i<groupsize; ++i) { ItemDataBean idb =
* (ItemDataBean)iddao.findByItemIdAndEventCRFIdAndOrdinal(ifmb
* .getItemId(), ecb.getId(), i+1); StringBuffer err = new StringBuffer();
* parsedExp = parser.parse(rob.getValue(), i+1);
* if(parser.getErrors().length()>0) { err.append(parser.getErrors());
* parser.setErrors(new StringBuffer()); } else { value =
* ScoreUtil.eval(parsedExp, err); //YW >> String exp = rob.getValue(); exp =
* exp.replace("##", ","); if(writeToDB(ib,idb,exp,value,err)) {
* itemdata.put(ib.getId()+"_"+(i+1), idb.getValue()); }else { String key =
* (i+1)>1 ? ifmb.getLeftItemText()+"_"+(i+1) : ifmb.getLeftItemText();
* updateFailedItems.add(key); } } if(err.length()>0) { String key = (i+1)>1 ?
* ifmb.getLeftItemText()+"_"+(i+1) : ifmb.getLeftItemText();
* errors.add("Item " + key + " contains calculation errors: " +
* err.toString()); } } } }
*
* //YW, 1-16-2008, for group-calculation type. Current restrictions: //1.
* an item with group-calculation type is not repeatable. //2. only
* calculate sum(), avg(), min(), max(), median(), stdev() //3. formula
* arguments only contain item beans //4. only one item bean per argument
* List<ItemFormMetadataBean> itemList =
* ifmdao.findAllByCRFVersionIdAndResponseTypeId( ecb.getCRFVersionId(),
* ResponseType.GROUP_CALCULATION.getId()); if(itemList.size()>0) {
* Collections.sort(itemList); for (ItemFormMetadataBean ifmb: itemList) {
* ItemBean ib = (ItemBean)idao.findByPK(ifmb.getItemId());
* ResponseOptionBean rob =
* (ResponseOptionBean)ifmb.getResponseSet().getOptions().get(0);
* StringBuffer err = new StringBuffer(); parser.setErrors(err); String
* parsedExp = parser.parse(rob.getValue(),itemOrdinals); String value = "";
* if(parser.getErrors().length()>0) { err.append(parser.getErrors()); }else {
* value = ScoreUtil.eval(parsedExp,err);
*
* ItemDataBean idb =
* (ItemDataBean)iddao.findByItemIdAndEventCRFIdAndOrdinal(ifmb
* .getItemId(), ecb.getId(), 1); String exp = rob.getValue(); exp =
* exp.replace("##", ","); if(writeToDB(ib,idb,exp,value,err)) {
* itemdata.put(ib.getId()+"_"+idb.getOrdinal(), idb.getValue()); } else {
* updateFailedItems.add(ifmb.getLeftItemText()); } }
*
* if(err.length()>0) { errors.add("Item " + ifmb.getLeftItemText() + "
* contains calculation errors: " + err.toString()); } } } } catch
* (OpenClinicaException e) { logger.error(e.getMessage()); }
* //ecb.setNeedsRecalc(false); //EventCRFDAO ecdao = new
* EventCRFDAO(sm.getDataSource()); //ecb = ecdao.update(ecb);
*
* return updateFailedItems; }
*/
/**
* Performs calculation. <br>
* Notice: both parameter 'itemdata' and parameter 'errs' might be updated
* in this method.
*
* @param displayItems
* @param items
* @param itemdata
* @param errs
* @return
*
* @author ywang (Jan. 2008)
*/
public String doCalculation(DisplayItemBean displayItem, HashMap<String, ItemBean> items, HashMap<String, String> itemdata, HashMap<Integer, TreeSet<Integer>> itemOrdinals, StringBuffer errs, int ordinal) {
if (itemdata == null) {
logger.error("In DataEntryServlet doCalculation(), itemdata map is empty!");
errs.append("Calculation cannot be started because needed items are empty" + "; ");
return "";
}
String value = "";
NumberFormat nf = NumberFormat.getInstance();
Parser parser = new Parser(items, itemdata);
ItemBean ib = displayItem.getItem();
ItemFormMetadataBean ifm = displayItem.getMetadata();
ResponseOptionBean rob = (ResponseOptionBean) ifm.getResponseSet().getOptions().get(0);
ArrayList<ScoreToken> parsedExp = new ArrayList<ScoreToken>();
int type = ifm.getResponseSet().getResponseTypeId();
if (type == 8) {
parsedExp = parser.assignVariables(parser.parseScoreTokens(rob.getValue()), ordinal);
} else if (type == 9) {
// YW, 1-16-2008, for group-calculation type. Current restrictions:
// 1. only calculate sum(), avg(), min(), max(), median(), stdev()
// 2. formula arguments only contain item beans
// 3. only one item bean per argument
parsedExp = parser.assignVariables(parser.parseScoreTokens(rob.getValue()), itemOrdinals);
}
if (parser.getErrors().length() > 0) {
errs.append(parser.getErrors());
} else {
try {
value = ScoreUtil.eval(parsedExp);
} catch (ScoreException se) {
logger.error(se.getMessage());
}
ItemDataType idt = ib.getDataType();
if (value == null || value.length() == 0) {
value = "";
String exp = rob.getValue();
exp = exp.replace("##", ",");
errs.append("Result is empty in" + " " + exp + "; ");
// errors.append(resexception.getString("result_is_empty_in") +
// " " + exp + "; ");
} else {
value = this.getMathContextValue(value, ifm, idt, errs);
}
// idb.setStatus(Status.UNAVAILABLE);
itemdata.put(ib.getId() + "_" + ordinal, value);
}
return value;
}
Aggregations