package org.openntf.domino.formula;
import java.util.Vector;
import java.util.logging.Logger;
import lotus.domino.NotesException;
import org.openntf.domino.Database;
import org.openntf.domino.Document;
import org.openntf.domino.Session;
import org.openntf.domino.WrapperFactory;
import org.openntf.domino.utils.Factory;
import org.openntf.domino.utils.Factory.SessionType;
import org.openntf.formula.EvaluateException;
import org.openntf.formula.FormulaContext;
import org.openntf.formula.Formulas;
import org.openntf.formula.ValueHolder;
public class FormulaContextNotes extends FormulaContext {
private static final Logger log_ = Logger.getLogger(FormulaContextNotes.class.getName());
static {
// this is not yet nice, but we assume that this context is always used in Domino/XPage environment
Factory.addTerminateHook(new Runnable() {
@Override
public void run() {
Formulas.terminate();
}
}, true);
}
/**
* does a native evaluate. This is needed for all functions that are too complex to implement in java or the algorithm is unknown
*
* @param formula
* the formula to evaluate
* @param params
* the parameters are mapped to the field p1, p2 and so on
* @return the value
*/
public ValueHolder evaluateNative(final String formula, final ValueHolder... params) {
Database db = getDatabase();
if (db == null)
throw new UnsupportedOperationException("No database set: Can't evaluate Lotus native formula");
Session session = db.getAncestorSession();
WrapperFactory wf = session.getFactory();
lotus.domino.Document rawDocument = wf.toLotus(getDocument());
Document tmpDoc = null;
if (params.length > 0) {
tmpDoc = db.createDocument();
rawDocument = session.getFactory().toLotus(tmpDoc);
// fill the document
for (int i = 0; i < params.length; i++) {
try {
tmpDoc.replaceItemValue("p" + (i + 1), params[i].toList());
} catch (EvaluateException e) {
return params[i];
}
}
} else {
rawDocument = wf.toLotus(getDocument());
}
try {
log_.warning("Evaluating native formula: '" + formula + "' This may affect performance");
lotus.domino.Session rawSession = wf.toLotus(session);
Vector<?> v = rawSession.evaluate(formula, rawDocument);
Vector<Object> wrapped = wf.wrapColumnValues(v, session);
rawSession.recycle(v);
return ValueHolder.valueOf(wrapped);
} catch (NotesException e) {
log_.warning("NotesException: " + e.text);
if (e.text.contains("Could not evaluate formula:"))
return ValueHolder.valueOf(new EvaluateException(-1, -1, e));
return ValueHolder.valueOf(new RuntimeException(e));
}
}
@Override
public String getEnv(final String varNameLC) {
return Factory.getSession(SessionType.CURRENT).getEnvironmentString(varNameLC);
}
@Override
public void setEnv(final String varName, final String value) {
Factory.getSession(SessionType.CURRENT).setEnvironmentVar(varName, value);
}
public Database getDatabase() {
Document doc = getDocument();
if (doc == null) {
return Factory.getSession(SessionType.CURRENT).getCurrentDatabase();
} else {
return doc.getAncestorDatabase();
}
}
public Document getDocument() {
return dataMap instanceof Document ? ((Document) dataMap) : null;
}
}