/** * Identify the itemset in the backend model, and create a set of SelectChoice objects at the * current question reference based on the data in the model. * * <p>Will modify the itemset binding to contain the relevant choices * * @param itemset The binding for an itemset, where the choices will be populated * @param curQRef A reference to the current question's element, which will be used to determine * the values to be chosen from. */ public void populateDynamicChoices(ItemsetBinding itemset, TreeReference curQRef) { Vector<SelectChoice> choices = new Vector<SelectChoice>(); Vector<TreeReference> matches = itemset.nodesetExpr.evalNodeset( this.getInstance(), new EvaluationContext(exprEvalContext, itemset.contextRef.contextualize(curQRef))); for (int i = 0; i < matches.size(); i++) { TreeReference item = matches.elementAt(i); String label = itemset.labelExpr.evalReadable( this.getInstance(), new EvaluationContext(exprEvalContext, item)); String value = null; TreeElement copyNode = null; if (itemset.copyMode) { copyNode = this.getInstance().resolveReference(itemset.copyRef.contextualize(item)); } if (itemset.valueRef != null) { value = itemset.valueExpr.evalReadable( this.getInstance(), new EvaluationContext(exprEvalContext, item)); } // SelectChoice choice = new SelectChoice(labelID,labelInnerText,value,isLocalizable); SelectChoice choice = new SelectChoice(label, value != null ? value : "dynamic:" + i, itemset.labelIsItext); choice.setIndex(i); if (itemset.copyMode) choice.copyNode = copyNode; choices.addElement(choice); } if (choices.size() == 0) { throw new RuntimeException( "dynamic select question has no choices! [" + itemset.nodesetRef + "]"); } itemset.setChoices(choices, this.getLocalizer()); }
public void copyItemsetAnswer(QuestionDef q, TreeElement targetNode, IAnswerData data) throws InvalidReferenceException { ItemsetBinding itemset = q.getDynamicChoices(); TreeReference targetRef = targetNode.getRef(); TreeReference destRef = itemset.getDestRef().contextualize(targetRef); Vector<Selection> selections = null; Vector<String> selectedValues = new Vector<String>(); if (data instanceof SelectMultiData) { selections = (Vector<Selection>) data.getValue(); } else if (data instanceof SelectOneData) { selections = new Vector<Selection>(); selections.addElement((Selection) data.getValue()); } if (itemset.valueRef != null) { for (int i = 0; i < selections.size(); i++) { selectedValues.addElement(selections.elementAt(i).choice.getValue()); } } // delete existing dest nodes that are not in the answer selection Hashtable<String, TreeElement> existingValues = new Hashtable<String, TreeElement>(); Vector<TreeReference> existingNodes = getInstance().expandReference(destRef); for (int i = 0; i < existingNodes.size(); i++) { TreeElement node = getInstance().resolveReference(existingNodes.elementAt(i)); if (itemset.valueRef != null) { String value = itemset .getRelativeValue() .evalReadable( this.getInstance(), new EvaluationContext(exprEvalContext, node.getRef())); if (selectedValues.contains(value)) { existingValues.put(value, node); // cache node if in selection and already exists } } // delete from target targetNode.removeChild(node); } // copy in nodes for new answer; preserve ordering in answer for (int i = 0; i < selections.size(); i++) { Selection s = selections.elementAt(i); SelectChoice ch = s.choice; TreeElement cachedNode = null; if (itemset.valueRef != null) { String value = ch.getValue(); if (existingValues.containsKey(value)) { cachedNode = existingValues.get(value); } } if (cachedNode != null) { cachedNode.setMult(i); targetNode.addChild(cachedNode); } else { getInstance().copyItemsetNode(ch.copyNode, destRef, this); } } triggerTriggerables( destRef); // trigger conditions that depend on the creation of these new nodes initializeTriggerables(destRef); // initialize conditions for the node (and sub-nodes) // not 100% sure this will work since destRef is ambiguous as the last step, but i think it's // supposed to work }