use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.
the class XFormParser method loadXmlInstance.
/**
* Loads a compatible xml instance into FormDef f
*
* call before f.initialize()!
*/
private static void loadXmlInstance(FormDef f, Document xmlInst) {
TreeElement savedRoot = XFormParser.restoreDataModel(xmlInst, null).getRoot();
TreeElement templateRoot = f.getMainInstance().getRoot().deepCopy(true);
// TODO: should check that namespaces match?
if (!savedRoot.getName().equals(templateRoot.getName()) || savedRoot.getMult() != 0) {
throw new RuntimeException("Saved form instance does not match template form definition");
}
// populate the data model
TreeReference tr = TreeReference.rootRef();
tr.add(templateRoot.getName(), TreeReference.INDEX_UNBOUND);
templateRoot.populate(savedRoot, f);
// populated model to current form
f.getMainInstance().setRoot(templateRoot);
// if the new instance is inserted into the formdef before f.initialize() is called, this
// locale refresh is unnecessary
// Localizer loc = f.getLocalizer();
// if (loc != null) {
// f.localeChanged(loc.getLocale(), loc);
// }
}
use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.
the class XFormParser method buildInstanceStructure.
/**
* Parses instance hierarchy and turns into a skeleton model; ignoring data content,
* but respecting repeated nodes and 'template' flags
*
* @param node the input node
* @param parent the parent
* @param instanceName the name of the instance
* @param docnamespace
* @param namespacePrefixesByUri namespace prefixes, by URI
* @param multiplicityFromGroup if not null, the multiplicity to use. If present, a potentially
* expensive search can be avoided.
* @return a new TreeElement
*/
public static TreeElement buildInstanceStructure(Element node, TreeElement parent, String instanceName, String docnamespace, Map<String, String> namespacePrefixesByUri, Integer multiplicityFromGroup) {
TreeElement element;
// catch when text content is mixed with children
int numChildren = node.getChildCount();
boolean hasText = false;
boolean hasElements = false;
for (int i = 0; i < numChildren; i++) {
switch(node.getType(i)) {
case Node.ELEMENT:
hasElements = true;
break;
case Node.TEXT:
if (node.getText(i).trim().length() > 0)
hasText = true;
break;
}
}
if (hasElements && hasText) {
Std.out.println("Warning: instance node '" + node.getName() + "' contains both elements and text as children; text ignored");
}
// check for repeat templating
final String name = node.getName();
final int multiplicity;
if (isTemplate(node)) {
multiplicity = TreeReference.INDEX_TEMPLATE;
if (parent != null && parent.getChild(name, TreeReference.INDEX_TEMPLATE) != null) {
throw new XFormParseException("More than one node declared as the template for the same repeated set [" + name + "]", node);
}
} else {
multiplicity = multiplicityFromGroup != null ? multiplicityFromGroup : (parent == null ? 0 : parent.getChildMultiplicity(name));
}
String modelType = node.getAttributeValue(NAMESPACE_JAVAROSA, "modeltype");
// create node; handle children
if (modelType == null) {
element = new TreeElement(name, multiplicity);
element.setInstanceName(instanceName);
} else {
if (typeMappings.get(modelType) == null) {
throw new XFormParseException("ModelType " + modelType + " is not recognized.", node);
}
element = (TreeElement) modelPrototypes.getNewInstance(typeMappings.get(modelType).toString());
if (element == null) {
element = new TreeElement(name, multiplicity);
Std.out.println("No model type prototype available for " + modelType);
} else {
element.setName(name);
element.setMult(multiplicity);
}
}
if (node.getNamespace() != null) {
if (!node.getNamespace().equals(docnamespace)) {
element.setNamespace(node.getNamespace());
}
if (namespacePrefixesByUri.containsKey(node.getNamespace())) {
element.setNamespacePrefix(namespacePrefixesByUri.get(node.getNamespace()));
}
}
if (hasElements) {
Integer newMultiplicityFromGroup = childOptimizationsOk(node) ? 0 : null;
for (int i = 0; i < numChildren; i++) {
if (node.getType(i) == Node.ELEMENT) {
TreeElement newChild = buildInstanceStructure(node.getElement(i), element, instanceName, docnamespace, namespacePrefixesByUri, newMultiplicityFromGroup);
element.addChild(newChild);
if (newMultiplicityFromGroup != null) {
newMultiplicityFromGroup++;
}
}
}
}
// handle attributes
if (node.getAttributeCount() > 0) {
for (int i = 0; i < node.getAttributeCount(); i++) {
String attrNamespace = node.getAttributeNamespace(i);
String attrName = node.getAttributeName(i);
if (attrNamespace.equals(NAMESPACE_JAVAROSA) && attrName.equals("template")) {
continue;
}
if (attrNamespace.equals(NAMESPACE_JAVAROSA) && attrName.equals("recordset")) {
continue;
}
element.setAttribute(attrNamespace, attrName, node.getAttributeValue(i));
}
}
return element;
}
use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.
the class FormInstanceParser method checkRepeatsForTemplate.
/**
* Helper function for checkRepeatsForTemplate
*/
private static void checkRepeatsForTemplate(TreeElement repeatTreeNode, TreeReference ref, FormInstance instance, List<TreeReference> missing) {
String name = repeatTreeNode.getName();
int mult = (repeatTreeNode.isRepeatable() ? TreeReference.INDEX_TEMPLATE : 0);
ref = ref.extendRef(name, mult);
if (repeatTreeNode.isRepeatable()) {
TreeElement template = instance.resolveReference(ref);
if (template == null) {
missing.add(ref);
}
}
for (int i = 0; i < repeatTreeNode.getNumChildren(); i++) {
checkRepeatsForTemplate(repeatTreeNode.getChildAt(i), ref, instance, missing);
}
}
use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.
the class FormInstanceParser method removeInvalidTemplates.
// helper function for removeInvalidTemplates
private boolean removeInvalidTemplates(TreeElement instanceNode, TreeElement repeatTreeNode, boolean templateAllowed) {
int mult = instanceNode.getMult();
boolean repeatable = repeatTreeNode != null && repeatTreeNode.isRepeatable();
if (mult == TreeReference.INDEX_TEMPLATE) {
if (!templateAllowed) {
reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Template nodes for sub-repeats must be located within the template node of the parent repeat; ignoring template... [" + instanceNode.getName() + "]", null);
return true;
} else if (!repeatable) {
reporter.warning(XFormParserReporter.TYPE_INVALID_STRUCTURE, "Warning: template node found for ref that is not repeatable; ignoring... [" + instanceNode.getName() + "]", null);
return true;
}
}
if (repeatable && mult != TreeReference.INDEX_TEMPLATE)
templateAllowed = false;
for (int i = 0; i < instanceNode.getNumChildren(); i++) {
TreeElement child = instanceNode.getChildAt(i);
TreeElement rchild = (repeatTreeNode == null ? null : repeatTreeNode.getChild(child.getName(), 0));
if (removeInvalidTemplates(child, rchild, templateAllowed)) {
instanceNode.removeChildAt(i);
i--;
}
}
return false;
}
use of org.javarosa.core.model.instance.TreeElement in project javarosa by opendatakit.
the class FormInstanceParser method parseInstance.
FormInstance parseInstance(Element e, boolean isMainInstance, String name, Map<String, String> namespacePrefixesByUri) {
TreeElement root = buildInstanceStructure(e, null, !isMainInstance ? name : null, e.getNamespace(), namespacePrefixesByUri, null);
FormInstance instanceModel = new FormInstance(root);
instanceModel.setName(isMainInstance ? formDef.getTitle() : name);
final List<String> usedAtts = Collections.unmodifiableList(Arrays.asList("id", "version", "uiVersion", "name"));
String schema = e.getNamespace();
if (schema != null && schema.length() > 0 && !schema.equals(defaultNamespace)) {
instanceModel.schema = schema;
}
instanceModel.formVersion = e.getAttributeValue(null, "version");
instanceModel.uiVersion = e.getAttributeValue(null, "uiVersion");
XFormParser.loadNamespaces(e, instanceModel);
if (isMainInstance) {
// the initialization of the references is done twice.
// The first time is here because they are needed before these
// validation steps can be performed.
// It is then done again during the call to _f.setInstance().
FormDef.updateItemsetReferences(formDef.getChildren());
processRepeats(instanceModel);
verifyBindings(instanceModel, e.getName());
verifyActions(instanceModel);
}
applyInstanceProperties(instanceModel);
// print unused attribute warning message for parent element
if (XFormUtils.showUnusedAttributeWarning(e, usedAtts)) {
reporter.warning(XFormParserReporter.TYPE_UNKNOWN_MARKUP, XFormUtils.unusedAttWarning(e, usedAtts), getVagueLocation(e));
}
return instanceModel;
}
Aggregations