private Submission getSubmissionById(String id) {
   if (context.getForm().getModel() == null) return null;
   for (Submission submission : context.getForm().getModel().getSubmissions()) {
     if (submission.getAttributes().get("id") != null
         && submission.getAttributes().get("id").equals(id)) return submission;
   }
   return null;
 }
 private Bind getBindByNodeset(String nodeset) {
   if (context.getForm().getModel() == null) return null;
   for (Bind bind : context.getForm().getModel().getBinds()) {
     Bind result = getBindByNodesetRecursive(bind, nodeset, "");
     if (result != null) return result;
   }
   return null;
 }
  public void exportERDF(Writer writer) {

    for (XFormsUIElement element : context.getForm().getChildElements()) {
      registerResourcesRecursive(element, context.getForm());
    }

    try {
      writer.append("<div class=\"processdata\">");
      appendFormERDF(writer);

      for (XFormsElement element : context.getRegisteredElements()) {
        appendElementERDF(writer, element);
      }

      writer.append("</div>");

    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  private void appendFormERDF(Writer writer) throws IOException {
    String name = context.getForm().getAttributes().get("name");
    if (name == null) name = "";

    String head = "";
    if (context.getForm().getHead() != null) {
      try {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        XMLSerializer serializer = new XMLSerializer();
        serializer.setOutputByteStream(stream);
        serializer.asDOMSerializer();
        serializer.setNamespaces(true);
        serializer.serialize(context.getForm().getHead());
        head = StringEscapeUtils.escapeXml(stream.toString());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    String nsDeclarations = "";
    for (String key : context.getForm().getNSDeclarations().keySet()) {
      nsDeclarations += "[" + key + "," + context.getForm().getNSDeclarations().get(key) + "]";
    }

    writer.append("<div id=\"" + context.getForm().getResourceId() + "\" class=\"-oryx-canvas\">");
    appendOryxField(writer, "type", STENCILSET_URI + "#" + context.getForm().getStencilId());
    appendXFormsField(writer, "id", "");
    appendXFormsField(writer, "name", name);
    appendXFormsField(writer, "version", "");
    appendXFormsField(writer, "head", head);
    appendXFormsField(writer, "nsdeclarations", nsDeclarations);
    appendOryxField(writer, "mode", "writable");
    appendOryxField(writer, "mode", "fullscreen");
    writer.append(
        "<a rel=\"oryx-stencilset\" href=\"/oryx/stencilsets/xforms/xforms.json\"/>"); // TODO: HACK
                                                                                       // TO MAKE IT
                                                                                       // WORK FOR
                                                                                       // NOW

    for (String id : context.getResourceIds()) {
      writer.append("<a rel=\"oryx-render\" href=\"#" + id + "\"/>");
    }

    writer.append("</div>");
  }
  /**
   * Recursively traverse all elements with stencil representations and register them - and parent
   * relationships between them - on export context
   *
   * @param element
   */
  private void registerResourcesRecursive(XFormsElement element, XFormsElement parent) {
    context.registerResource(element, parent);

    if (element instanceof UIElementContainer) {
      for (XFormsUIElement child : ((UIElementContainer) element).getChildElements()) {
        registerResourcesRecursive(child, element);
      }
    }
    if (element instanceof ListUICommonContainer) {
      for (ListUICommon child : ((ListUICommonContainer) element).getListUICommons()) {
        registerResourcesRecursive(child, element);
      }
    }
    if (element instanceof ActionContainer) {
      for (AbstractAction child : ((ActionContainer) element).getActions()) {
        registerResourcesRecursive(child, element);
      }
    }
    if (element instanceof Switch) {
      for (Case child : ((Switch) element).getCases()) {
        registerResourcesRecursive(child, element);
      }
    }
    if (element instanceof LabelContainer) {
      Label label = ((LabelContainer) element).getLabel();
      if (label != null) registerResourcesRecursive(label, element);
    }
    if (element instanceof UICommonContainer) {

      Help help = ((UICommonContainer) element).getHelp();
      if (help != null) registerResourcesRecursive(help, element);

      Hint hint = ((UICommonContainer) element).getHint();
      if (hint != null) registerResourcesRecursive(hint, element);

      Alert alert = ((UICommonContainer) element).getAlert();
      if (alert != null) registerResourcesRecursive(alert, element);
    }
  }
  private void appendElementERDF(Writer writer, XFormsElement element) throws IOException {
    writer.append("<div id=\"" + element.getResourceId() + "\">");
    appendOryxField(writer, "type", STENCILSET_URI + "#" + element.getStencilId());

    for (String field : element.getAttributes().keySet()) {
      if (!field.equals("bind"))
        appendXFormsField(writer, field, element.getAttributes().get(field));
    }

    // handle PCData containers
    if (element instanceof PCDataContainer) {
      String content = ((PCDataContainer) element).getContent();
      if (element instanceof Label) {
        appendXFormsField(writer, "text", content);
      } else {
        appendXFormsField(writer, "message", content);
      }
    }

    // handle model item properties
    String ref = element.getAttributes().get("ref");
    if (ref != null) {

      if (!ref.startsWith("/") && (element instanceof XFormsUIElement)) {
        ref = getNodesetContext((XFormsUIElement) element) + ref;
      }

      Bind bind = getBindByNodeset(ref);

      if (bind != null) {
        for (String field : bind.getAttributes().keySet()) {
          if (!field.equals("id") && !field.equals("nodeset"))
            appendXFormsField(writer, field, bind.getAttributes().get(field));
        }
      }
    }

    // handle submission properties
    String submissionId = element.getAttributes().get("submission");
    if (submissionId != null) {
      Submission submission = getSubmissionById(submissionId);
      if (submission != null) {
        for (String field : submission.getAttributes().keySet()) {
          if (!field.equals("id"))
            appendXFormsField(writer, field, submission.getAttributes().get(field));
        }
      }
    }

    // handle item element
    if (element instanceof Item) {
      Item item = (Item) element;
      Value value = item.getValue();
      if (value != null) {
        for (String field : value.getAttributes().keySet()) {
          if (!field.equals("id"))
            appendXFormsField(writer, "value_" + field, value.getAttributes().get(field));
        }
      }
      appendOryxField(writer, "bounds", "0," + item.getYPosition() + ",0," + item.getYPosition());
    }

    // handle itemset element
    if (element instanceof Itemset) {
      Itemset itemset = (Itemset) element;
      Value value = itemset.getValue();
      if (value != null) {
        for (String field : value.getAttributes().keySet()) {
          appendXFormsField(writer, "value_" + field, value.getAttributes().get(field));
        }
      }
      Copy copy = ((Itemset) element).getCopy();
      if (copy != null) {
        for (String field : copy.getAttributes().keySet()) {
          appendXFormsField(writer, "copy_" + field, copy.getAttributes().get(field));
        }
      }
      appendOryxField(
          writer, "bounds", "0," + itemset.getYPosition() + ",0," + itemset.getYPosition());
    }

    if (element instanceof XFormsUIElement) {
      int x = ((XFormsUIElement) element).getXPosition();
      int y = (((XFormsUIElement) element).getYPosition() + 10) * DISTANCE_FACTOR;
      appendOryxField(writer, "bounds", x + "," + y + "," + x + "," + y);
    }

    writer.append(
        "<a rel=\"raziel-parent\" href=\"#" + context.getParent(element).getResourceId() + "\"/>");
    writer.append("</div>");
  }