/** * recursively write out a node of the instance * @param out * @param e * @param ref * @throws IOException */ private void writeTreeElement(BinaryWriter out_, TreeElement e) { TreeElement templ = instance.getTemplatePath(e.getRef()); Boolean isGroup = !templ.isLeaf(); if (isGroup) { ArrayList childTypesHandled = new ArrayList(); for (int i = 0; i < templ.getNumChildren(); i++) { String childName = templ.getChildAt(i).getName(); if (!childTypesHandled.Contains(childName)) { childTypesHandled.Add(childName); int mult = e.getChildMultiplicity(childName); if (mult > 0 && !e.getChild(childName, 0).isRelevant()) { mult = 0; } ExtUtil.writeNumeric(out_, mult); for (int j = 0; j < mult; j++) { writeTreeElement(out_, e.getChild(childName, j)); } } } } else { ExtUtil.write(out_, new ExtWrapAnswerData(this, e.dataType, e.getValue())); } }
/** * recursively read in a node of the instance, by filling out the template instance * @param e * @param ref * @param in * @param pf * @throws IOException * @throws DeserializationException */ private void readTreeElement(TreeElement e, BinaryReader in_, PrototypeFactory pf) { TreeElement templ = instance.getTemplatePath(e.getRef()); Boolean isGroup = !templ.isLeaf(); if (isGroup) { ArrayList childTypes = new ArrayList(); for (int i = 0; i < templ.getNumChildren(); i++) { String childName = templ.getChildAt(i).getName(); if (!childTypes.Contains(childName)) { childTypes.Add(childName); } } for (int i = 0; i < childTypes.Count; i++) { String childName = (String)childTypes[i]; TreeReference childTemplRef = e.getRef().extendRef(childName, 0); TreeElement childTempl = instance.getTemplatePath(childTemplRef); Boolean repeatable = childTempl.repeatable; int n = ExtUtil.readInt(in_); Boolean relevant = (n > 0); if (!repeatable && n > 1) { throw new DeserializationException("Detected repeated instances of a non-repeatable node"); } if (repeatable) { int mult = e.getChildMultiplicity(childName); for (int j = mult - 1; j >= 0; j--) { e.removeChild(childName, j); } for (int j = 0; j < n; j++) { TreeReference dstRef = e.getRef().extendRef(childName, j); try { instance.copyNode(childTempl, dstRef); } catch (InvalidReferenceException ire) { //If there is an invalid reference, this is a malformed instance, //so we'll throw a Deserialization exception. TreeReference r = ire.InvalidReference; if (r == null) { throw new DeserializationException("Null Reference while attempting to deserialize! " + ire.Message); } else { throw new DeserializationException("Invalid Reference while attemtping to deserialize! Reference: " + r.toString(true) + " | " + ire.Message); } } TreeElement child = e.getChild(childName, j); child.setRelevant(true); readTreeElement(child, in_, pf); } } else { TreeElement child = e.getChild(childName, 0); child.setRelevant(relevant); if (relevant) { readTreeElement(child, in_, pf); } } } } else { e.setValue((IAnswerData)ExtUtil.read(in_, new ExtWrapAnswerData(e.dataType))); } }
//note: code overlap with FormDef.copyItemsetAnswer public IAnswerData getAnswerValue() { QuestionDef q = getQuestion(); ItemsetBinding itemset = q.getDynamicChoices(); if (itemset != null) { if (itemset.valueRef != null) { List <SelectChoice> choices = getSelectChoices(); List <String> preselectedValues = new List <String>(); //determine which selections are already present in the answer if (itemset.copyMode) { TreeReference destRef = itemset.getDestRef().contextualize(mTreeElement.getRef()); List <TreeReference> subNodes = form.Instance.expandReference(destRef); for (int i = 0; i < subNodes.Count; i++) { TreeElement node = form.Instance.resolveReference(subNodes[i]); String value = itemset.getRelativeValue().evalReadable(form.Instance, new EvaluationContext(form.exprEvalContext, node.getRef())); preselectedValues.Add(value); } } else { List <Selection> sels = new List <Selection>(); IAnswerData data = mTreeElement.getValue(); if (data is SelectMultiData) { sels = (List <Selection>)data.Value; } else if (data is SelectOneData) { sels = new List <Selection>(); sels.Add((Selection)data.Value); } for (int i = 0; i < sels.Count; i++) { preselectedValues.Add(sels[i].xmlValue); } } //populate 'selection' with the corresponding choices (matching 'value') from the dynamic choiceset List <Selection> selection = new List <Selection>(); for (int i = 0; i < preselectedValues.Count; i++) { String value = preselectedValues[i]; SelectChoice choice = null; for (int j = 0; j < choices.Count; j++) { SelectChoice ch = choices[j]; if (value.Equals(ch.Value)) { choice = ch; break; } } selection.Add(choice.selection()); } //convert to IAnswerData if (selection.Count == 0) { return(null); } else if (q.ControlType == Constants.CONTROL_SELECT_MULTI) { return(new SelectMultiData(selection)); } else if (q.ControlType == Constants.CONTROL_SELECT_ONE) { return(new SelectOneData(selection[0])); //do something if more than one selected? } else { throw new SystemException("can't happen"); } } else { return(null); //cannot map up selections without <value> } } else { //static choices return(mTreeElement.getValue()); } }