Example #1
0
  /**
   * @param elements
   * @param multiplicities
   * @return
   */
  public TreeReference getChildInstanceRef(Vector elements, Vector multiplicities) {
    if (elements.size() == 0) return null;

    // get reference for target element
    TreeReference ref =
        FormInstance.unpackReference(((IFormElement) elements.lastElement()).getBind()).clone();
    for (int i = 0; i < ref.size(); i++) {
      // There has to be a better way to encapsulate this
      if (ref.getMultiplicity(i) != TreeReference.INDEX_ATTRIBUTE) {
        ref.setMultiplicity(i, 0);
      }
    }

    // fill in multiplicities for repeats along the way
    for (int i = 0; i < elements.size(); i++) {
      IFormElement temp = (IFormElement) elements.elementAt(i);
      if (temp instanceof GroupDef && ((GroupDef) temp).getRepeat()) {
        TreeReference repRef = FormInstance.unpackReference(temp.getBind());
        if (repRef.isParentOf(ref, false)) {
          int repMult = ((Integer) multiplicities.elementAt(i)).intValue();
          ref.setMultiplicity(repRef.size() - 1, repMult);
        } else {
          return null; // question/repeat hierarchy is not consistent
          // with instance instance and bindings
        }
      }
    }

    return ref;
  }
  public static void applyDataType(
      FormInstance dm, String path, TreeReference parent, int dataType) {
    TreeReference ref = childRef(path, parent);

    Vector v = dm.expandReference(ref);
    for (int i = 0; i < v.size(); i++) {
      TreeElement e = dm.resolveReference((TreeReference) v.elementAt(i));
      e.dataType = dataType;
    }
  }
Example #3
0
  public void createNewRepeat(FormIndex index) throws InvalidReferenceException {
    TreeReference destRef = getChildInstanceRef(index);
    TreeElement template = instance.getTemplate(destRef);

    instance.copyNode(template, destRef);

    preloadInstance(instance.resolveReference(destRef));
    triggerTriggerables(destRef); // trigger conditions that depend on the creation of this new node
    initializeTriggerables(destRef); // initialize conditions for the node (and sub-nodes)
  }
Example #4
0
  public void setInstance(FormInstance instance) {
    if (instance.getFormId() != -1 && getID() != instance.getFormId()) {
      System.err.println(
          "Warning: assigning incompatible instance (type "
              + instance.getFormId()
              + ") to a formdef (type "
              + getID()
              + ")");
    }

    instance.setFormId(getID());
    this.instance = instance;
    attachControlsToInstanceData();
  }
	public void formEntrySaved(FormDef form, FormInstance instanceData, boolean formWasCompleted) {
		System.out.println("form is complete: " + formWasCompleted);
 
		//Warning, this might be null
		final SubmissionProfile profile = form.getSubmissionProfile();
		
		if (formWasCompleted) {
			
			// We want to cache this send before we actually ask, otherwise the user could quit before it is
			// either sent _or_ saved.
			
			IStorageUtility storage = StorageManager.getStorage(FormInstance.STORAGE_KEY);
			try {
				Logger.log("formentry","writing data: " + instanceData.getName());
				storage.write(instanceData);
				final int record = instanceData.getID();

				TransportMessage message = JRDemoContext._().buildMessage(instanceData, profile);
				
				CompletedFormOptionsState completed = new CompletedFormOptionsState(message) {
	
					public void sendData(TransportMessage message) {
						
						JRDemoFormTransportState send = new JRDemoFormTransportState(message, record) {
							public void done() {
								JRDemoUtil.goToList(cameFromFormList);
							}
		
							public void sendToBackground() {
								JRDemoUtil.goToList(cameFromFormList);
							}
						};
							
						send.start();
					}
	
					public void skipSend(TransportMessage message) {
						// Message should already be cached.
						abort();
					}
				};
				completed.start();
			} catch (StorageFullException e) {
				new RuntimeException("Storage full, unable to save data.");
			}
		} else {
			abort();
		}
	}
  public static void mergeDataModel(
      FormInstance parent, FormInstance child, TreeReference parentRef) {
    TreeElement parentNode = parent.resolveReference(parentRef);
    // ugly
    if (parentNode == null) {
      parentRef = parent.addNode(parentRef);
      parentNode = parent.resolveReference(parentRef);
    }
    TreeElement childNode = child.getRoot();

    int mult = parentNode.getChildMultiplicity(childNode.getName());
    childNode.setMult(mult);

    parentNode.addChild(childNode);
  }
Example #7
0
 private void evaluateTriggerable(Triggerable t, TreeReference anchorRef) {
   TreeReference contextRef = t.contextRef.contextualize(anchorRef);
   Vector v = instance.expandReference(contextRef);
   for (int i = 0; i < v.size(); i++) {
     EvaluationContext ec = new EvaluationContext(exprEvalContext, (TreeReference) v.elementAt(i));
     t.apply(instance, ec, this);
   }
 }
Example #8
0
  public boolean isRepeatRelevant(TreeReference repeatRef) {
    boolean relev = true;

    Condition c = (Condition) conditionRepeatTargetIndex.get(repeatRef.genericize());
    if (c != null) {
      relev = c.evalBool(instance, new EvaluationContext(exprEvalContext, repeatRef));
    }

    // check the relevancy of the immediate parent
    if (relev) {
      TreeElement templNode = instance.getTemplate(repeatRef);
      TreeReference parentPath = templNode.getParent().getRef().genericize();
      TreeElement parentNode = instance.resolveReference(parentPath.contextualize(repeatRef));
      relev = parentNode.isRelevant();
    }

    return relev;
  }
Example #9
0
  /**
   * Deletes the inner-most repeat that this node belongs to and returns the corresponding
   * FormIndex. Behavior is currently undefined if you call this method on a node that is not
   * contained within a repeat.
   *
   * @param index
   * @return
   */
  public FormIndex deleteRepeat(FormIndex index) {
    Vector indexes = new Vector();
    Vector multiplicities = new Vector();
    Vector elements = new Vector();
    collapseIndex(index, indexes, multiplicities, elements);

    // loop backwards through the elements, removing objects from each
    // vector, until we find a repeat
    // TODO: should probably check to make sure size > 0
    for (int i = elements.size() - 1; i >= 0; i--) {
      IFormElement e = (IFormElement) elements.elementAt(i);
      if (e instanceof GroupDef && ((GroupDef) e).getRepeat()) {
        break;
      } else {
        indexes.removeElementAt(i);
        multiplicities.removeElementAt(i);
        elements.removeElementAt(i);
      }
    }

    // build new formIndex which includes everything
    // up to the node we're going to remove
    FormIndex newIndex = buildIndex(indexes, multiplicities, elements);

    TreeReference deleteRef = getChildInstanceRef(newIndex);
    TreeElement deleteElement = instance.resolveReference(deleteRef);
    TreeReference parentRef = deleteRef.getParentRef();
    TreeElement parentElement = instance.resolveReference(parentRef);

    int childMult = deleteElement.getMult();
    parentElement.removeChild(deleteElement);

    // update multiplicities of other child nodes
    for (int i = 0; i < parentElement.getNumChildren(); i++) {
      TreeElement child = parentElement.getChildAt(i);
      if (child.getMult() > childMult) {
        child.setMult(child.getMult() - 1);
      }
    }

    triggerTriggerables(deleteRef);
    return newIndex;
  }
Example #10
0
  /**
   * meant to be called after deserialization and initialization of handlers
   *
   * @param newInstance true if the form is to be used for a new entry interaction, false if it is
   *     using an existing IDataModel
   */
  public void initialize(boolean newInstance) {
    if (newInstance) { // only preload new forms (we may have to revisit
      // this)
      preloadInstance(instance.getRoot());
    }

    if (getLocalizer() != null && getLocalizer().getLocale() == null) {
      getLocalizer().setToDefault();
    }

    initializeTriggerables();
  }
Example #11
0
  public boolean evaluateConstraint(TreeReference ref, IAnswerData data) {
    if (data == null) return true;

    TreeElement node = instance.resolveReference(ref);
    Constraint c = node.getConstraint();
    if (c == null) return true;

    EvaluationContext ec = new EvaluationContext(exprEvalContext, ref);
    ec.isConstraint = true;
    ec.candidateValue = data;

    return c.constraint.eval(instance, ec);
  }
  public static Object getValue(String xpath, TreeReference context, FormInstance tree) {
    TreeElement node = tree.resolveReference(ref(xpath).contextualize(context));
    if (node == null) {
      throw new RuntimeException(
          "Could not find node [" + xpath + "] when parsing saved instance!");
    }

    if (node.isRelevant()) {
      IAnswerData val = node.getValue();
      return (val == null ? null : val.getValue());
    } else {
      return null;
    }
  }
Example #13
0
  public int getNumRepetitions(FormIndex index) {
    Vector indexes = new Vector();
    Vector multiplicities = new Vector();
    Vector elements = new Vector();

    if (!index.isInForm()) {
      throw new RuntimeException("not an in-form index");
    }

    collapseIndex(index, indexes, multiplicities, elements);

    if (!(elements.lastElement() instanceof GroupDef)
        || !((GroupDef) elements.lastElement()).getRepeat()) {
      throw new RuntimeException("current element not a repeat");
    }

    // so painful
    TreeElement templNode = instance.getTemplate(index.getReference());
    TreeReference parentPath = templNode.getParent().getRef().genericize();
    TreeElement parentNode =
        instance.resolveReference(parentPath.contextualize(index.getReference()));
    return parentNode.getChildMultiplicity(templNode.getName());
  }
Example #14
0
  public static QuestionDef findQuestionByRef(TreeReference ref, IFormElement fe) {
    if (fe instanceof FormDef) {
      ref = ref.genericize();
    }

    if (fe instanceof QuestionDef) {
      QuestionDef q = (QuestionDef) fe;
      TreeReference bind = FormInstance.unpackReference(q.getBind());
      return (ref.equals(bind) ? q : null);
    } else {
      for (int i = 0; i < fe.getChildren().size(); i++) {
        QuestionDef ret = findQuestionByRef(ref, fe.getChild(i));
        if (ret != null) return ret;
      }
      return null;
    }
  }
  public static void addData(FormInstance dm, String xpath, Object data, int dataType) {
    if (data == null) {
      dataType = -1;
    }

    IAnswerData val;
    switch (dataType) {
      case -1:
        val = null;
        break;
      case Constants.DATATYPE_TEXT:
        val = new StringData((String) data);
        break;
      case Constants.DATATYPE_INTEGER:
        val = new IntegerData((Integer) data);
        break;
      case Constants.DATATYPE_LONG:
        val = new LongData((Long) data);
        break;
      case Constants.DATATYPE_DECIMAL:
        val = new DecimalData((Double) data);
        break;
      case Constants.DATATYPE_BOOLEAN:
        val = new StringData(((Boolean) data).booleanValue() ? "t" : "f");
        break;
      case Constants.DATATYPE_DATE:
        val = new DateData((Date) data);
        break;
      case Constants.DATATYPE_DATE_TIME:
        val = new DateTimeData((Date) data);
        break;
      case Constants.DATATYPE_TIME:
        val = new TimeData((Date) data);
        break;
      case Constants.DATATYPE_CHOICE_LIST:
        val = (SelectMultiData) data;
        break;
      default:
        throw new IllegalArgumentException("Don't know how to handle data type [" + dataType + "]");
    }

    TreeReference ref = absRef(xpath, dm);
    if (dm.addNode(ref, val, dataType) == null) {
      throw new RuntimeException("error setting value during object backup [" + xpath + "]");
    }
  }
  public static void importRMS(FormInstance dm, IStorageUtility storage, Class type, String path) {
    if (!Externalizable.class.isAssignableFrom(type) || !Restorable.class.isAssignableFrom(type)) {
      return;
    }

    boolean idMatters = Persistable.class.isAssignableFrom(type);

    String childName = ((Restorable) PrototypeFactory.getInstance(type)).getRestorableType();
    TreeElement e = dm.resolveReference(absRef(path, dm));
    Vector children = e.getChildrenWithName(childName);

    for (int i = 0; i < children.size(); i++) {
      FormInstance child = subDataModel((TreeElement) children.elementAt(i));

      Restorable inst = (Restorable) PrototypeFactory.getInstance(type);

      // restore record id first so 'importData' has access to it
      int recID = -1;
      if (idMatters) {
        recID = ((Integer) getValue(RECORD_ID_TAG, child)).intValue();
        ((Persistable) inst).setID(recID);
      }

      inst.importData(child);

      try {
        if (idMatters) {
          storage.write((Persistable) inst);
        } else {
          storage.add((Externalizable) inst);
        }
      } catch (Exception ex) {
        throw new RuntimeException(
            "Error importing RMS during restore! ["
                + type.getName()
                + ":"
                + recID
                + "]; "
                + ex.getMessage());
      }
    }
  }
Example #17
0
 public boolean postProcessInstance() {
   return postProcessInstance(instance.getRoot());
 }
Example #18
0
  public void finalizeTriggerables() {
    //
    // DAGify the triggerables based on dependencies and sort them so that
    // trigbles come only after the trigbles they depend on
    //

    Vector partialOrdering = new Vector();
    for (int i = 0; i < triggerables.size(); i++) {
      Triggerable t = (Triggerable) triggerables.elementAt(i);
      Vector deps = new Vector();

      if (t.canCascade()) {
        for (int j = 0; j < t.getTargets().size(); j++) {
          TreeReference target = (TreeReference) t.getTargets().elementAt(j);
          Vector triggered = (Vector) triggerIndex.get(target);
          if (triggered != null) {
            for (int k = 0; k < triggered.size(); k++) {
              Triggerable u = (Triggerable) triggered.elementAt(k);
              if (!deps.contains(u)) deps.addElement(u);
            }
          }
        }
      }

      for (int j = 0; j < deps.size(); j++) {
        Triggerable u = (Triggerable) deps.elementAt(j);
        Triggerable[] edge = {t, u};
        partialOrdering.addElement(edge);
      }
    }

    Vector vertices = new Vector();
    for (int i = 0; i < triggerables.size(); i++) vertices.addElement(triggerables.elementAt(i));
    triggerables.removeAllElements();

    while (vertices.size() > 0) {
      // determine root nodes
      Vector roots = new Vector();
      for (int i = 0; i < vertices.size(); i++) {
        roots.addElement(vertices.elementAt(i));
      }
      for (int i = 0; i < partialOrdering.size(); i++) {
        Triggerable[] edge = (Triggerable[]) partialOrdering.elementAt(i);
        roots.removeElement(edge[1]);
      }

      // if no root nodes while graph still has nodes, graph has cycles
      if (roots.size() == 0) {
        throw new RuntimeException(
            "Cannot create partial ordering of triggerables due to dependency cycle. Why wasn't this caught during parsing?");
      }

      // remove root nodes and edges originating from them
      for (int i = 0; i < roots.size(); i++) {
        Triggerable root = (Triggerable) roots.elementAt(i);
        triggerables.addElement(root);
        vertices.removeElement(root);
      }
      for (int i = partialOrdering.size() - 1; i >= 0; i--) {
        Triggerable[] edge = (Triggerable[]) partialOrdering.elementAt(i);
        if (roots.contains(edge[0])) partialOrdering.removeElementAt(i);
      }
    }

    triggerablesInOrder = true;

    //
    // build the condition index for repeatable nodes
    //

    conditionRepeatTargetIndex = new Hashtable();
    for (int i = 0; i < triggerables.size(); i++) {
      Triggerable t = (Triggerable) triggerables.elementAt(i);
      if (t instanceof Condition) {
        Vector targets = t.getTargets();
        for (int j = 0; j < targets.size(); j++) {
          TreeReference target = (TreeReference) targets.elementAt(j);
          if (instance.getTemplate(target) != null) {
            conditionRepeatTargetIndex.put(target, (Condition) t);
          }
        }
      }
    }
  }
 public static TreeReference topRef(FormInstance dm) {
   return ref("/" + dm.getRoot().getName());
 }
 private static FormInstance newDataModel(String topTag) {
   FormInstance dm = new FormInstance();
   dm.addNode(ref("/" + topTag));
   return dm;
 }
 public static FormInstance createRootDataModel(Restorable r) {
   FormInstance inst = createDataModel(r);
   inst.schema = "http://openrosa.org/backup";
   addData(inst, "timestamp", new Date(), Constants.DATATYPE_DATE_TIME);
   return inst;
 }
Example #22
0
 public void setAnswer(IAnswerData data, TreeReference ref) {
   setAnswer(data, instance.resolveReference(ref));
 }
Example #23
0
 public void setValue(IAnswerData data, TreeReference ref) {
   setValue(data, ref, instance.resolveReference(ref));
 }
Example #24
0
 /**
  * Link a deserialized instance back up with its parent FormDef. this allows select/select1
  * questions to be internationalizable in chatterbox, and (if using CHOICE_INDEX mode) allows the
  * instance to be serialized to xml
  */
 public void attachControlsToInstanceData() {
   attachControlsToInstanceData(instance.getRoot());
 }