package org.openrosa.client.jr.core.model; import java.io.IOException; import java.util.Vector; import org.openrosa.client.java.io.DataInputStream; import org.openrosa.client.java.io.DataOutputStream; import org.openrosa.client.jr.core.model.condition.IConditionExpr; import org.openrosa.client.jr.core.model.instance.FormInstance; import org.openrosa.client.jr.core.model.instance.TreeReference; import org.openrosa.client.jr.core.model.util.restorable.RestoreUtils; import org.openrosa.client.jr.core.services.locale.Localizable; import org.openrosa.client.jr.core.services.locale.Localizer; import org.openrosa.client.jr.core.util.externalizable.DeserializationException; import org.openrosa.client.jr.core.util.externalizable.ExtUtil; import org.openrosa.client.jr.core.util.externalizable.ExtWrapNullable; import org.openrosa.client.jr.core.util.externalizable.ExtWrapTagged; import org.openrosa.client.jr.core.util.externalizable.Externalizable; import org.openrosa.client.jr.core.util.externalizable.PrototypeFactory; public class ItemsetBinding implements Externalizable, Localizable { /** * note that storing both the ref and expr for everything is kind of redundant, but we're forced * to since it's nearly impossible to convert between the two w/o having access to the underlying * xform/xpath classes, which we don't from the core model project */ public TreeReference nodesetRef; //absolute ref of itemset source nodes public IConditionExpr nodesetExpr; //path expression for source nodes; may be relative, may contain predicates public TreeReference contextRef; //context ref for nodesetExpr; ref of the control parent (group/formdef) of itemset question //note: this is only here because its currently impossible to both (a) get a form control's parent, and (b) //convert expressions into refs while preserving predicates. once these are fixed, this field can go away public TreeReference labelRef; //absolute ref of label public IConditionExpr labelExpr; //path expression for label; may be relative, no predicates public boolean labelIsItext; //if true, content of 'label' is an itext id public boolean copyMode; //true = copy subtree; false = copy string value public TreeReference copyRef; //absolute ref to copy public TreeReference valueRef; //absolute ref to value public IConditionExpr valueExpr; //path expression for value; may be relative, no predicates (must be relative if copy mode) private TreeReference destRef; //ref that identifies the repeated nodes resulting from this itemset //not serialized -- set by QuestionDef.setDynamicChoices() private Vector<SelectChoice> choices; //dynamic choices -- not serialized, obviously public Vector<SelectChoice> getChoices () { return choices; } public void setChoices (Vector<SelectChoice> choices, Localizer localizer) { if (this.choices != null) { System.out.println("warning: previous choices not cleared out"); clearChoices(); } this.choices = choices; //init localization if (localizer != null) { String curLocale = localizer.getLocale(); if (curLocale != null) { localeChanged(curLocale, localizer); } } } public void clearChoices () { this.choices = null; } public void localeChanged(String locale, Localizer localizer) { if (choices != null) { for (int i = 0; i < choices.size(); i++) { choices.elementAt(i).localeChanged(locale, localizer); } } } public void setDestRef (QuestionDef q) { destRef = FormInstance.unpackReference(q.getBind()).clone(); if (copyMode) { destRef.add(copyRef.getNameLast(), TreeReference.INDEX_UNBOUND); } } public TreeReference getDestRef () { return destRef; } public IConditionExpr getRelativeValue () { TreeReference relRef = null; if (copyRef == null) { relRef = valueRef; //must be absolute in this case } else if (valueRef != null) { relRef = valueRef.relativize(copyRef); } return relRef != null ? RestoreUtils.xfFact.refToPathExpr(relRef) : null; } public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException { nodesetRef = (TreeReference)ExtUtil.read(in, TreeReference.class, pf); nodesetExpr = (IConditionExpr)ExtUtil.read(in, new ExtWrapTagged(), pf); contextRef = (TreeReference)ExtUtil.read(in, TreeReference.class, pf); labelRef = (TreeReference)ExtUtil.read(in, TreeReference.class, pf); labelExpr = (IConditionExpr)ExtUtil.read(in, new ExtWrapTagged(), pf); valueRef = (TreeReference)ExtUtil.read(in, new ExtWrapNullable(TreeReference.class), pf); valueExpr = (IConditionExpr)ExtUtil.read(in, new ExtWrapNullable(new ExtWrapTagged()), pf); copyRef = (TreeReference)ExtUtil.read(in, new ExtWrapNullable(TreeReference.class), pf); labelIsItext = ExtUtil.readBool(in); copyMode = ExtUtil.readBool(in); } public void writeExternal(DataOutputStream out) throws IOException { ExtUtil.write(out, nodesetRef); ExtUtil.write(out, new ExtWrapTagged(nodesetExpr)); ExtUtil.write(out, contextRef); ExtUtil.write(out, labelRef); ExtUtil.write(out, new ExtWrapTagged(labelExpr)); ExtUtil.write(out, new ExtWrapNullable(valueRef)); ExtUtil.write(out, new ExtWrapNullable(valueExpr == null ? null : new ExtWrapTagged(valueExpr))); ExtUtil.write(out, new ExtWrapNullable(copyRef)); ExtUtil.writeBool(out, labelIsItext); ExtUtil.writeBool(out, copyMode); } }