use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method getChildInstanceRef.
public TreeReference getChildInstanceRef(List<IFormElement> elements, List<Integer> multiplicities) {
if (elements.size() == 0)
return null;
IFormElement element = elements.get(elements.size() - 1);
// get reference for target element
TreeReference ref = FormInstance.unpackReference(element.getBind()).clone();
for (int i = 0; i < ref.size(); i++) {
// There has to be a better way to encapsulate this
if (ref.getMultiplicity(i) != TreeReference.INDEX_ATTRIBUTE) {
ref.setMultiplicity(i, 0);
}
}
// fill in multiplicities for repeats along the way
for (int i = 0; i < elements.size(); i++) {
IFormElement temp = elements.get(i);
if (temp instanceof GroupDef && ((GroupDef) temp).getRepeat()) {
TreeReference repRef = FormInstance.unpackReference(temp.getBind());
if (repRef.isParentOf(ref, false)) {
int repMult = multiplicities.get(i);
ref.setMultiplicity(repRef.size() - 1, repMult);
} else {
// question/repeat hierarchy is not consistent
return null;
// with instance instance and bindings
}
}
}
return ref;
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method createNewRepeat.
public void createNewRepeat(FormIndex index) throws InvalidReferenceException {
TreeReference destRef = getChildInstanceRef(index);
TreeElement template = mainInstance.getTemplate(destRef);
mainInstance.copyNode(template, destRef);
TreeElement newNode = mainInstance.resolveReference(destRef);
preloadInstance(newNode);
// 2013-05-14 - ctsims - Events should get fired _before_ calculate stuff
// is fired, moved
// this above triggering triggerables
// Grab any actions listening to this event
List<Action> listeners = getEventListeners(Action.EVENT_JR_INSERT);
for (Action a : listeners) {
a.processAction(this, destRef);
}
TreeReference parentRef = destRef.getParentRef();
TreeElement parentElement = mainInstance.resolveReference(parentRef);
dagImpl.createRepeatGroup(getMainInstance(), getEvaluationContext(), destRef, parentElement, newNode);
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method canCreateRepeat.
public boolean canCreateRepeat(TreeReference repeatRef, FormIndex repeatIndex) {
GroupDef repeat = (GroupDef) this.getChild(repeatIndex);
// Check to see if this repeat can have children added by the user
if (repeat.noAddRemove) {
// should have
if (repeat.getCountReference() != null) {
int currentMultiplicity = repeatIndex.getElementMultiplicity();
// Lu Gram: the count XPath needs to be contextualized for nested
// repeat groups...
TreeReference countRef = FormInstance.unpackReference(repeat.getCountReference());
TreeElement countNode = this.getMainInstance().resolveReference(countRef.contextualize(repeatRef));
if (countNode == null) {
throw new RuntimeException("Could not locate the repeat count value expected at " + repeat.getCountReference().getReference().toString());
}
// get the total multiplicity possible
IAnswerData count = countNode.getValue();
long fullcount = count == null ? 0 : (Integer) count.getValue();
if (fullcount <= currentMultiplicity) {
return false;
}
} else {
// Otherwise the user can never add repeat instances
return false;
}
}
return true;
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method getAbsRef.
// take a (possibly relative) reference, and make it absolute based on its parent
// moved from the parser to this class so it can be used more cleanly by ItemsetBinding
public static IDataReference getAbsRef(IDataReference ref, TreeReference parentRef) {
TreeReference tref;
if (!parentRef.isAbsolute()) {
throw new RuntimeException("XFormParser.getAbsRef: parentRef must be absolute");
}
if (ref != null) {
tref = (TreeReference) ref.getReference();
} else {
// only happens for <group>s with no binding
tref = TreeReference.selfRef();
}
tref = tref.parent(parentRef);
if (tref == null) {
throw new XFormParseException("Binding path [" + tref + "] not allowed with parent binding of [" + parentRef + "]");
}
return new XPathReference(tref);
}
use of org.javarosa.core.model.instance.TreeReference in project javarosa by opendatakit.
the class FormDef method initEvalContext.
/**
* @param ec The new Evaluation Context
*/
private void initEvalContext(EvaluationContext ec) {
if (!ec.getFunctionHandlers().containsKey("jr:itext")) {
final FormDef f = this;
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "jr:itext";
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
String textID = (String) args[0];
try {
// SUUUUPER HACKY
String form = ec.getOutputTextForm();
if (form != null) {
textID = textID + ";" + form;
String result = f.getLocalizer().getRawText(f.getLocalizer().getLocale(), textID);
return result == null ? "" : result;
} else {
String text = f.getLocalizer().getText(textID);
return text == null ? "[itext:" + textID + "]" : text;
}
} catch (NoSuchElementException nsee) {
return "[nolocale]";
}
}
@Override
public List<Class[]> getPrototypes() {
Class[] proto = { String.class };
List<Class[]> v = new ArrayList<Class[]>(1);
v.add(proto);
return v;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
});
}
/*
* function to reverse a select value into the display label for that
* choice in the question it came from
*
* arg 1: select value arg 2: string xpath referring to origin question;
* must be absolute path
*
* this won't work at all if the original label needed to be
* processed/calculated in some way (<output>s, etc.) (is this even
* allowed?) likely won't work with multi-media labels _might_ work for
* itemsets, but probably not very well or at all; could potentially work
* better if we had some context info DOES work with localization
*
* it's mainly intended for the simple case of reversing a question with
* compile-time-static fields, for use inside an <output>
*/
if (!ec.getFunctionHandlers().containsKey("jr:choice-name")) {
final FormDef f = this;
ec.addFunctionHandler(new IFunctionHandler() {
@Override
public String getName() {
return "jr:choice-name";
}
@Override
public Object eval(Object[] args, EvaluationContext ec) {
try {
String value = (String) args[0];
String questionXpath = (String) args[1];
TreeReference ref = RestoreUtils.xfFact.ref(questionXpath);
QuestionDef q = findQuestionByRef(ref, f);
if (q == null || (q.getControlType() != Constants.CONTROL_SELECT_ONE && q.getControlType() != Constants.CONTROL_SELECT_MULTI)) {
return "";
}
// NOTE: this is highly suspect. We have no context against
// which to evaluate
// a dynamic selection list. This will generally cause that
// evaluation to break
// if any filtering is done, or, worst case, give unexpected
// results.
//
// We should hook into the existing code (FormEntryPrompt) for
// pulling
// display text for select choices. however, it's hard,
// because we don't really have
// any context to work with, and all the situations where that
// context would be used
// don't make sense for trying to reverse a select value back
// to a label in an unrelated
// expression
List<SelectChoice> choices;
ItemsetBinding itemset = q.getDynamicChoices();
if (itemset != null) {
if (itemset.getChoices() == null) {
if (ref.isAmbiguous()) {
// SurveyCTO: We need a absolute "ref" to populate the dynamic choices,
// like we do when we populate those at FormEntryPrompt (line 251).
// The "ref" here is ambiguous, so we need to make it concrete first.
ref = ref.contextualize(ec.getContextRef());
}
f.populateDynamicChoices(itemset, ref);
}
choices = itemset.getChoices();
} else {
// static choices
choices = q.getChoices();
}
if (choices != null) {
for (SelectChoice ch : choices) {
if (ch.getValue().equals(value)) {
// this is really not ideal. we should hook into the
// existing code (FormEntryPrompt) for pulling
// display text for select choices. however, it's
// hard, because we don't really have
// any context to work with, and all the situations
// where that context would be used
// don't make sense for trying to reverse a select
// value back to a label in an unrelated
// expression
String textID = ch.getTextID();
String templateStr;
if (textID != null) {
templateStr = f.getLocalizer().getText(textID);
} else {
templateStr = ch.getLabelInnerText();
}
return fillTemplateString(templateStr, ref);
}
}
}
return "";
} catch (Exception e) {
throw new WrappedException("error in evaluation of xpath function [choice-name]", e);
}
}
@Override
public List<Class[]> getPrototypes() {
Class[] proto = { String.class, String.class };
List<Class[]> v = new ArrayList<Class[]>(1);
v.add(proto);
return v;
}
@Override
public boolean rawArgs() {
return false;
}
@Override
public boolean realTime() {
return false;
}
});
}
}
Aggregations