public IDataPointer[] retrieveExternalDataPointer(IAnswerData data) { IEnumerator en = additionalSerializers.GetEnumerator(); while (en.MoveNext()) { IAnswerDataSerializer serializer = (IAnswerDataSerializer)en.Current; Boolean contains = serializer.containsExternalData(data); if (contains != null) { return(serializer.retrieveExternalDataPointer(data)); } } if (data is PointerAnswerData) { IDataPointer[] pointer = new IDataPointer[1]; pointer[0] = (IDataPointer)((PointerAnswerData)data).getValue(); return(pointer); } else if (data is MultiPointerAnswerData) { return((IDataPointer[])((MultiPointerAnswerData)data).Value); } //This shouldn't have been called. return(null); }
//this method is for copying in the answers to an itemset. the template node of the destination //is used for overall structure (including data types), and the itemset source node is used for //raw data. note that data may be coerced across types, which may result in type conversion error //very similar in structure to populate() public void populateTemplate(TreeElement incoming, FormDef f) { if (this.isLeaf()) { IAnswerData value = incoming.value; if (value == null) { this.setValue(null); } else { Type classType = CompactInstanceWrapper.classForDataType(this.dataType); if (classType == null) { throw new SystemException("data type [" + value.GetType().Name + "] not supported inside itemset"); } else if (classType.IsAssignableFrom(value.GetType()) && !(value is SelectOneData || value is SelectMultiData)) { this.setValue(value); } else { String textVal = RestoreUtils.xfFact.serializeData(value); IAnswerData typedVal = RestoreUtils.xfFact.parseData(textVal, this.dataType, this.getRef(), f); this.setValue(typedVal); } } } else { for (int i = 0; i < this.getNumChildren(); i++) { TreeElement child = this.getChildAt(i); List <TreeElement> newChildren = incoming.getChildrenWithName(child.getName()); if (child.repeatable) { for (int k = 0; k < newChildren.Count; k++) { TreeElement template = f.Instance.getTemplate(child.getRef()); TreeElement newChild = template.deepCopy(false); newChild.setMult(k); this.children.Insert(i + k + 1, newChild); newChild.populateTemplate((TreeElement)newChildren[k], f); } i += newChildren.Count; } else { child.populateTemplate((TreeElement)newChildren[0], f); } } } }
/** * saveAnswer attempts to save the current answer into the data model * without doing any constraint checking. Only use this if you know what * you're doing. For normal form filling you should always use * answerQuestion or answerCurrentQuestion. * * @param index * @param data * @return true if saved successfully, false otherwise. */ public Boolean saveAnswer(FormIndex index, IAnswerData data) { if (model.getEvent(index) != FormEntryController.EVENT_QUESTION) { throw new SystemException("Non-Question object at the form index."); } TreeElement element = model.getTreeElement(index); return(commitAnswer(element, index, data)); }
public void setValue(IAnswerData value) { if (isLeaf()) { this.value = value; } else { throw new SystemException("Can't set data value for node that has children!"); } }
/* ==== SPECIAL SETTERS (SETTERS WITH SIDE-EFFECTS) ==== */ public Boolean setAnswer(IAnswerData answer) { if (value != null || answer != null) { setValue(answer); alertStateObservers(FormElementStateListener_Fields.CHANGE_DATA); return(true); } else { return(false); } }
/** * commitAnswer actually saves the data into the datamodel. * * @param element * @param index * @param data * @return true if saved successfully, false otherwise */ private Boolean commitAnswer(TreeElement element, FormIndex index, IAnswerData data) { if (data != null || element.getValue() != null) { // we should check if the data to be saved is already the same as // the data in the model, but we can't (no IAnswerData.equals()) model.getForm().setValue(data, index.getReference(), element); return(true); } else { return(false); } }
public Boolean canSerialize(IAnswerData data) { if (data is StringData || data is DateData || data is TimeData || data is SelectMultiData || data is SelectOneData || data is IntegerData || data is DecimalData || data is PointerAnswerData || data is MultiPointerAnswerData || data is GeoPointData || data is LongData || data is DateTimeData || data is UncastData) { return(true); } else { return(false); } }
public static Object unpackValue(IAnswerData val) { if (val == null) { return(""); } else if (val is UncastData) { return(val.Value); } else if (val is IntegerData) { return(( Double)(((int)val.Value))); } else if (val is LongData) { return(( Double)(((long)val.Value))); } else if (val is DecimalData) { return(val.Value); } else if (val is StringData) { return(val.Value); } else if (val is SelectOneData) { return(((Selection)val.Value).Value); } else if (val is SelectMultiData) { return((new XFormAnswerDataSerializer()).serializeAnswerData(val)); } else if (val is DateData) { return(val.Value); } else if (val is BooleanData) { return(val.Value); } else { Console.WriteLine("warning: unrecognized data type in xpath expr: " + val.GetType().Name); return(val.Value); //is this a good idea? } }
public String getAnswerText() { IAnswerData data = this.getAnswerValue(); if (data == null) { return(null); } else { String text; //[email protected] - Aug 11, 2010 - Added special logic to //capture and display the appropriate value for selections //and multi-selects. if (data is SelectOneData) { text = this.getSelectItemText((Selection)data); } else if (data is SelectMultiData) { String returnValue = ""; List <Selection> values = (List <Selection>)data; foreach (Selection value in values) { returnValue += this.getSelectItemText(value) + " "; } text = returnValue; } else { text = data.DisplayText; } if (getControlType() == Constants.CONTROL_SECRET) { String obfuscated = ""; for (int i = 0; i < text.Length; ++i) { obfuscated += "*"; } text = obfuscated; } return(text); } }
/** * Attempts to save the answer at the specified FormIndex into the * datamodel. * * @param index * @param data * @return OK if save was successful, error if a constraint was violated. */ public int answerQuestion(FormIndex index, IAnswerData data) { QuestionDef q = model.getQuestionPrompt(index).getQuestion(); if (model.getEvent(index) != FormEntryController.EVENT_QUESTION) { throw new SystemException("Non-Question object at the form index."); } TreeElement element = model.getTreeElement(index); Boolean complexQuestion = q.isComplex(); Boolean hasConstraints = false; if (element.required && data == null) { return(ANSWER_REQUIRED_BUT_EMPTY); } else if (!complexQuestion && !model.getForm().evaluateConstraint(index.getReference(), data)) { return(ANSWER_CONSTRAINT_VIOLATED); } else if (!complexQuestion) { commitAnswer(element, index, data); return(ANSWER_OK); } else if (complexQuestion && hasConstraints) { //TODO: itemsets: don't currently evaluate constraints for itemset/copy -- haven't figured out how handle it yet throw new SystemException("Itemsets do not currently evaluate constraints. Your constraint will not work, please remove it before proceeding."); } else { try { model.getForm().copyItemsetAnswer(q, element, data); } catch (InvalidReferenceException ire) { Console.WriteLine(ire.StackTrace); throw new SystemException("Invalid reference while copying itemset answer: " + ire.Message); } return(ANSWER_OK); } }
public Object serializeAnswerData(IAnswerData data, int dataType) { // First, we want to go through the additional serializers, as they should // take priority to the default serializations IEnumerator en = additionalSerializers.GetEnumerator(); while (en.MoveNext()) { IAnswerDataSerializer serializer = (IAnswerDataSerializer)en.Current; if (serializer.canSerialize(data)) { return(serializer.serializeAnswerData(data, dataType)); } } //Defaults Object result = serializeAnswerData(data); return(result); }
public TreeReference addNode(TreeReference ambigRef, IAnswerData data, int dataType) { TreeReference ref_ = ambigRef.clone(); TreeElement node = createNode(ref_); if (node != null) { if (dataType >= 0) { node.dataType = dataType; } node.setValue(data); return(ref_); } else { return(null); } }
public String getConstraintText(String textForm, IAnswerData attemptedValue) { if (mTreeElement.getConstraint() == null) { return(null); } else { EvaluationContext ec = new EvaluationContext(form.exprEvalContext, mTreeElement.getRef()); if (textForm != null) { ec.OutputTextForm = textForm; } if (attemptedValue != null) { ec.isConstraint = true; ec.candidateValue = attemptedValue; } return(mTreeElement.getConstraint().getConstraintMessage(ec, form.Instance)); } }
/* * (non-Javadoc) * @see org.javarosa.core.model.IAnswerDataSerializer#containsExternalData(org.javarosa.core.model.data.IAnswerData) */ public Boolean containsExternalData(IAnswerData data) { //First check for registered serializers to identify whether //they override this one. IEnumerator en = additionalSerializers.GetEnumerator(); while (en.MoveNext()) { IAnswerDataSerializer serializer = (IAnswerDataSerializer)en.Current; Boolean contains = serializer.containsExternalData(data); if (contains != null) { return(contains); } } if (data is PointerAnswerData || data is MultiPointerAnswerData) { return(true); } return(false); }
/** * For the current index: Checks whether the index represents a node which * should exist given a non-interactive repeat, along with a count for that * repeat which is beneath the dynamic level specified. * * If this index does represent such a node, the new model for the repeat is * created behind the scenes and the index for the initial question is * returned. * * Note: This method will not prevent the addition of new repeat elements in * the interface, it will merely use the xforms repeat hint to create new * nodes that are assumed to exist * * @param The index to be evaluated as to whether the underlying model is * hinted to exist */ private void createModelIfNecessary(FormIndex index) { if (index.isInForm()) { IFormElement e = getForm().getChild(index); if (e is GroupDef) { GroupDef g = (GroupDef)e; if (g.Repeat && g.CountReference != null) { IAnswerData count = getForm().Instance.getDataValue(g.CountReference); if (count != null) { long fullcount = ((int)count.Value); TreeReference ref_ = getForm().getChildInstanceRef(index); TreeElement element = getForm().Instance.resolveReference(ref_); if (element == null) { if (index.getInstanceIndex() < fullcount) { try { getForm().createNewRepeat(index); } catch (InvalidReferenceException ire) { Console.WriteLine(ire.StackTrace); throw new SystemException("Invalid Reference while creting new repeat!" + ire.Message); } } } } } } } }
public ExtWrapAnswerData(CompactInstanceWrapper instance, int dataType, IAnswerData val) { this.val = val; this.dataType = dataType; }
public String serializeData(IAnswerData data) { return((String)(new XFormAnswerDataSerializer().serializeAnswerData(data))); }
//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()); } }
public String getConstraintText(IAnswerData attemptedValue) { return(getConstraintText(null, attemptedValue)); }
/** * saveAnswer attempts to save the current answer into the data model * without doing any constraint checking. Only use this if you know what * you're doing. For normal form filling you should always use * answerQuestion(). * * @param index * @param data * @return true if saved successfully, false otherwise. */ public Boolean saveAnswer(IAnswerData data) { return(saveAnswer(model.getFormIndex(), data)); }
//rebuilding a node from an imported instance // there's a lot of error checking we could do on the received instance, but it's // easier to just ignore the parts that are incorrect public void populate(TreeElement incoming, FormDef f) { if (this.isLeaf()) { // check that incoming doesn't have children? IAnswerData value = incoming.getValue(); if (value == null) { this.setValue(null); } else if (this.dataType == Constants.DATATYPE_TEXT || this.dataType == Constants.DATATYPE_NULL) { this.setValue(value); // value is a StringData } else { String textVal = value.ToString(); IAnswerData typedVal = RestoreUtils.xfFact.parseData(textVal, this.dataType, this.getRef(), f); this.setValue(typedVal); } } else { ArrayList names = new ArrayList(); for (int i = 0; i < this.getNumChildren(); i++) { TreeElement child = this.getChildAt(i); if (!names.Contains(child.getName())) { names.Add(child.getName()); } } // remove all default repetitions from skeleton data model (_preserving_ templates, though) for (int i = 0; i < this.getNumChildren(); i++) { TreeElement child = this.getChildAt(i); if (child.repeatable && child.getMult() != TreeReference.INDEX_TEMPLATE) { this.removeChildAt(i); i--; } } // make sure ordering is preserved (needed for compliance with xsd schema) if (this.getNumChildren() != names.Count) { throw new SystemException("sanity check failed"); } for (int i = 0; i < this.getNumChildren(); i++) { TreeElement child = this.getChildAt(i); String expectedName = (String)names[i]; if (!child.getName().Equals(expectedName)) { TreeElement child2 = null; int j; for (j = i + 1; j < this.getNumChildren(); j++) { child2 = this.getChildAt(j); if (child2.getName().Equals(expectedName)) { break; } } if (j == this.getNumChildren()) { throw new SystemException("sanity check failed"); } this.removeChildAt(j); this.children.Insert(i, child2); } } // java i hate you so much for (int i = 0; i < this.getNumChildren(); i++) { TreeElement child = this.getChildAt(i); List <TreeElement> newChildren = incoming.getChildrenWithName(child.getName()); if (child.repeatable) { for (int k = 0; k < newChildren.Count; k++) { TreeElement newChild = child.deepCopy(true); newChild.setMult(k); this.children.Insert(i + k + 1, newChild); newChild.populate((TreeElement)newChildren[k], f); } i += newChildren.Count; } else { if (newChildren.Count == 0) { child.setRelevant(false); } else { child.populate((TreeElement)newChildren[0], f); } } } } }
/* ==== SERIALIZATION ==== */ /* * TODO: * * this new serialization scheme is kind of lame. ideally, we shouldn't have * to sub-class TreeElement at all; we should have an API that can * seamlessly represent complex data model objects (like weight history or * immunizations) as if they were explicity XML subtrees underneath the * parent TreeElement * * failing that, we should wrap this scheme in an ExternalizableWrapper */ /* * (non-Javadoc) * * @see * org.javarosa.core.services.storage.utilities.Externalizable#readExternal * (java.io.DataInputStream) */ public void readExternal(BinaryReader in_renamed, PrototypeFactory pf) { name = ExtUtil.nullIfEmpty(ExtUtil.readString(in_renamed)); multiplicity = ExtUtil.readInt(in_renamed); repeatable = ExtUtil.readBool(in_renamed); value = (IAnswerData)ExtUtil.read(in_renamed, new ExtWrapNullable(new ExtWrapTagged()), pf); // children = ExtUtil.nullIfEmpty((Vector)ExtUtil.read(in, new // ExtWrapList(TreeElement.class), pf)); // Jan 22, 2009 - [email protected] // old line: children = ExtUtil.nullIfEmpty((Vector)ExtUtil.read(in, new // ExtWrapList(TreeElement.class), pf)); // New Child deserialization // 1. read null status as boolean // 2. read number of children // 3. for i < number of children // 3.1 if read boolean true , then create TreeElement and deserialize // directly. // 3.2 if read boolean false then create tagged element and deserialize // child if (!ExtUtil.readBool(in_renamed)) { // 1. children = null; } else { children = new ArrayList(); // 2. int numChildren = (int)ExtUtil.readNumeric(in_renamed); // 3. for (int i = 0; i < numChildren; ++i) { Boolean normal = ExtUtil.readBool(in_renamed); TreeElement child; if (normal) { // 3.1 child = new TreeElement(); child.readExternal(in_renamed, pf); } else { // 3.2 child = (TreeElement)ExtUtil.read(in_renamed, new ExtWrapTagged(), pf); } child.setParent(this); children.Add(child); } } // end Jan 22, 2009 dataType = ExtUtil.readInt(in_renamed); relevant = ExtUtil.readBool(in_renamed); required = ExtUtil.readBool(in_renamed); enabled = ExtUtil.readBool(in_renamed); relevantInherited = ExtUtil.readBool(in_renamed); enabledInherited = ExtUtil.readBool(in_renamed); constraint = (Constraint)ExtUtil.read(in_renamed, new ExtWrapNullable( typeof(Constraint)), pf); preloadHandler = ExtUtil.nullIfEmpty(ExtUtil.readString(in_renamed)); preloadParams = ExtUtil.nullIfEmpty(ExtUtil.readString(in_renamed)); ArrayList attStrings = ExtUtil.nullIfEmpty((ArrayList)ExtUtil.read(in_renamed, new ExtWrapList(typeof(String)), pf)); setAttributesFromSingleStringVector(attStrings); }
/** * Attempts to save answer at the current FormIndex into the datamodel. * * @param data * @return */ public int answerQuestion(IAnswerData data) { return(answerQuestion(model.getFormIndex(), data)); }
public Object serializeAnswerData(IAnswerData data) { if (data is StringData) { return(serializeAnswerData((StringData)data)); } else if (data is SelectMultiData) { return(serializeAnswerData((SelectMultiData)data)); } else if (data is SelectOneData) { return(serializeAnswerData((SelectOneData)data)); } else if (data is IntegerData) { return(serializeAnswerData((IntegerData)data)); } else if (data is LongData) { return(serializeAnswerData((LongData)data)); } else if (data is DecimalData) { return(serializeAnswerData((DecimalData)data)); } else if (data is DateData) { return(serializeAnswerData((DateData)data)); } else if (data is TimeData) { return(serializeAnswerData((TimeData)data)); } else if (data is PointerAnswerData) { return(serializeAnswerData((PointerAnswerData)data)); } else if (data is MultiPointerAnswerData) { return(serializeAnswerData((MultiPointerAnswerData)data)); } else if (data is GeoPointData) { return(serializeAnswerData((GeoPointData)data)); } else if (data is DateTimeData) { return(serializeAnswerData((DateTimeData)data)); } else if (data is BooleanData) { return(serializeAnswerData((BooleanData)data)); } else if (data is UncastData) { return(serializeAnswerData((UncastData)data)); } return(null); }