//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); } } } }
public TreeElement deepCopy(Boolean includeTemplates) { TreeElement newNode = shallowCopy(); newNode.children = new ArrayList(); for (int i = 0; i < children.Count; i++) { TreeElement child = (TreeElement)children[i]; if (includeTemplates || child.getMult() != TreeReference.INDEX_TEMPLATE) { newNode.addChild(child.deepCopy(includeTemplates)); } } return(newNode); }
// for making new repeat instances; 'from' and 'to' must be unambiguous // references EXCEPT 'to' may be ambiguous at its final step // return true is successfully copied, false otherwise public TreeElement copyNode(TreeElement src, TreeReference to) { if (!to.isAbsolute()) { throw new InvalidReferenceException("Destination reference must be absolute for copying", to); } // strip out dest node info and get dest parent String dstName = to.getNameLast(); int dstMult = to.getMultLast(); TreeReference toParent = to.getParentRef(); TreeElement parent = resolveReference(toParent); if (parent == null) { throw new InvalidReferenceException("Null parent reference whle attempting to copy", toParent); } if (!parent.isChildable()) { throw new InvalidReferenceException("Invalid Parent Node: cannot accept children.", toParent); } if (dstMult == TreeReference.INDEX_UNBOUND) { dstMult = parent.getChildMultiplicity(dstName); } else if (parent.getChild(dstName, dstMult) != null) { throw new InvalidReferenceException("Destination already exists!", to); } TreeElement dest = src.deepCopy(false); dest.setName(dstName); dest.multiplicity = dstMult; parent.addChild(dest); return(dest); }
//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); } } } } }