Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix namespaced TreeElements #696

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 39 additions & 19 deletions src/main/java/org/javarosa/core/model/instance/TreeElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.HashMap;
import java.util.List;

import java.util.Objects;
import org.javarosa.core.model.Constants;
import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.FormElementStateListener;
Expand All @@ -36,6 +37,7 @@
import org.javarosa.core.model.instance.utils.IAnswerResolver;
import org.javarosa.core.model.instance.utils.ITreeVisitor;
import org.javarosa.core.model.instance.utils.TreeElementChildrenList;
import org.javarosa.core.model.instance.utils.TreeElementNameComparator;
import org.javarosa.core.model.util.restorable.RestoreUtils;
import org.javarosa.core.util.DataUtil;
import org.javarosa.core.util.externalizable.DeserializationException;
Expand Down Expand Up @@ -125,19 +127,15 @@ public TreeElement(String name, int multiplicity) {
attributes = new ArrayList<TreeElement>(0);
}

/**
* Construct a TreeElement which represents an attribute with the provided
* namespace and name.
*
* @param namespace - if null will be converted to empty string
* @param name
* @param value
* @return A new instance of a TreeElement
*/
public static TreeElement constructAttributeElement(String namespace, String name, String value) {
return constructAttributeElement(namespace, null, name, value);
}

public static TreeElement constructAttributeElement(String namespace, String namespacePrefix, String name, String value) {
TreeElement element = new TreeElement(name);
element.setIsAttribute(true);
element.namespace = (namespace == null) ? "" : namespace;
element.setNamespace(namespace);
element.setNamespacePrefix(namespacePrefix);
element.multiplicity = TreeReference.INDEX_ATTRIBUTE;
element.value = new UncastData(value);
return element;
Expand All @@ -161,15 +159,24 @@ private void setIsAttribute(boolean attribute) {
*/
public static TreeElement getAttribute(List<TreeElement> attributes, String namespace, String name) {
for (TreeElement attribute : attributes) {
if(attribute.getName().equals(name) && (namespace == null || namespace.equals(attribute.namespace))) {
return attribute;
if (name.contains(":")) {
if (TreeElementNameComparator.elementMatchesName(attribute, name)) {
return attribute;
}
} else {
if (attribute.getName().equals(name) && (Objects.equals(namespace, attribute.namespace)
|| (Objects.equals(attribute.namespace, "") && namespace == null))) {
return attribute;
}
}
}
return null;
}

public static void setAttribute(TreeElement parent, List<TreeElement> attrs, String namespace, String name, String value) {
setAttribute(parent, attrs, namespace, null, name, value);
}

public static void setAttribute(TreeElement parent, List<TreeElement> attrs, String namespace, String namespacePrefix, String name, String value) {
TreeElement attribut = getAttribute(attrs, namespace, name);
if ( attribut != null ) {
if (value == null) {
Expand All @@ -184,7 +191,7 @@ public static void setAttribute(TreeElement parent, List<TreeElement> attrs, Str
if ( value == null ) return;

// create an attribute...
TreeElement attr = TreeElement.constructAttributeElement(namespace, name, value);
TreeElement attr = TreeElement.constructAttributeElement(namespace, namespacePrefix, name, value);
attr.setParent(parent);

attrs.add(attr);
Expand Down Expand Up @@ -340,7 +347,7 @@ public TreeElement shallowCopy() {

newNode.attributes = new ArrayList<>(attributes.size());
for (TreeElement attr : attributes) {
newNode.setAttribute(attr.getNamespace(), attr.getName(), attr.getAttributeValue());
newNode.setAttribute(attr.getNamespace(), attr.getNamespacePrefix(), attr.getName(), attr.getAttributeValue());
}

if (value != null) {
Expand Down Expand Up @@ -437,7 +444,7 @@ private void setRelevant(boolean relevant, boolean inherited) {
public void setBindAttributes(List<TreeElement> bindAttributes ) {
// create new tree elements for all the bind definitions...
for ( TreeElement ref : bindAttributes ) {
setBindAttribute(ref.getNamespace(), ref.getName(), ref.getAttributeValue());
setBindAttribute(ref.getNamespace(), ref.getNamespacePrefix(), ref.getName(), ref.getAttributeValue());
}
}

Expand Down Expand Up @@ -476,8 +483,8 @@ public String getBindAttributeValue(String namespace, String name) {
return element == null ? null: getAttributeValue(element);
}

public void setBindAttribute(String namespace, String name, String value) {
setAttribute(this, bindAttributes, namespace, name, value);
public void setBindAttribute(String namespace, String namespacePrefix, String name, String value) {
setAttribute(this, bindAttributes, namespace, namespacePrefix, name, value);
}

public void setEnabled(boolean enabled) {
Expand Down Expand Up @@ -556,6 +563,10 @@ public String getAttributeNamespace(int index) {
return attributes.get(index).namespace;
}

public String getAttributeNamespacePrefix(int index) {
return attributes.get(index).namespacePrefix;
}

@Override
public String getAttributeName(int index) {
return attributes.get(index).name;
Expand Down Expand Up @@ -602,6 +613,10 @@ public void setAttribute(String namespace, String name, String value) {
setAttribute(this, attributes, namespace, name, value);
}

public void setAttribute(String namespace, String namespacePrefix, String name, String value) {
setAttribute(this, attributes, namespace, namespacePrefix, name, value);
}

/* ==== SERIALIZATION ==== */

/*
Expand Down Expand Up @@ -677,6 +692,8 @@ public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOExcep
bindAttributes = ExtUtil.readAttributes(in, this);

attributes = ExtUtil.readAttributes(in, this);

namespacePrefix = ExtUtil.nullIfEmpty(ExtUtil.readString(in));
}

@Override
Expand Down Expand Up @@ -731,6 +748,8 @@ public void writeExternal(DataOutputStream out) throws IOException {
ExtUtil.writeAttributes(out, bindAttributes);

ExtUtil.writeAttributes(out, attributes);

ExtUtil.writeString(out, ExtUtil.emptyIfNull(namespacePrefix));
}

//rebuilding a node from an imported instance
Expand Down Expand Up @@ -828,9 +847,10 @@ public void populate(TreeElement incoming, FormDef f) {
for (int i = 0; i < incoming.getAttributeCount(); i++) {
String name = incoming.getAttributeName(i);
String ns = incoming.getAttributeNamespace(i);
String nsPrefix = incoming.getAttributeNamespacePrefix(i);
String value = incoming.getAttributeValue(i);

this.setAttribute(ns, name, value);
this.setAttribute(ns, nsPrefix, name, value);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package org.javarosa.core.model.instance.utils;

import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.jetbrains.annotations.Nullable;
import static org.javarosa.core.model.instance.TreeReference.DEFAULT_MULTIPLICITY;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import static org.javarosa.core.model.instance.TreeReference.DEFAULT_MULTIPLICITY;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.jetbrains.annotations.Nullable;

/**
* A collection of {@link TreeElement} children. They are stored in an {@link ArrayList}.
Expand Down Expand Up @@ -100,7 +99,7 @@ private void checkAndSetSameNameAndNormalMult(String name, int mult) {
*/
private boolean sameNameAndNormalMult(String name, int mult) {
return allHaveSameNameAndNormalMult && mult >= 0 &&
(children.isEmpty() || name.equals(children.get(0).getName()));
(children.isEmpty() || TreeElementNameComparator.elementMatchesName(children.get(0), name));
}

/**
Expand Down Expand Up @@ -190,7 +189,7 @@ private ElementAndLoc getChildAndLoc(String name, int multiplicity) {

for (int i = 0; i < children.size(); i++) {
TreeElement child = children.get(i);
if (name.equals(child.getName()) && child.getMult() == multiplicity) {
if (TreeElementNameComparator.elementMatchesName(child, name) && child.getMult() == multiplicity) {
return new ElementAndLoc(child, i);
}
}
Expand Down
88 changes: 44 additions & 44 deletions src/main/java/org/javarosa/xform/parse/XFormParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,48 @@

package org.javarosa.xform.parse;

import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableSet;
import static org.javarosa.core.model.Constants.CONTROL_AUDIO_CAPTURE;
import static org.javarosa.core.model.Constants.CONTROL_FILE_CAPTURE;
import static org.javarosa.core.model.Constants.CONTROL_IMAGE_CHOOSE;
import static org.javarosa.core.model.Constants.CONTROL_INPUT;
import static org.javarosa.core.model.Constants.CONTROL_OSM_CAPTURE;
import static org.javarosa.core.model.Constants.CONTROL_RANGE;
import static org.javarosa.core.model.Constants.CONTROL_RANK;
import static org.javarosa.core.model.Constants.CONTROL_SECRET;
import static org.javarosa.core.model.Constants.CONTROL_SELECT_MULTI;
import static org.javarosa.core.model.Constants.CONTROL_SELECT_ONE;
import static org.javarosa.core.model.Constants.CONTROL_TRIGGER;
import static org.javarosa.core.model.Constants.CONTROL_UPLOAD;
import static org.javarosa.core.model.Constants.CONTROL_VIDEO_CAPTURE;
import static org.javarosa.core.model.Constants.DATATYPE_CHOICE;
import static org.javarosa.core.model.Constants.DATATYPE_MULTIPLE_ITEMS;
import static org.javarosa.core.model.Constants.XFTAG_UPLOAD;
import static org.javarosa.core.services.ProgramFlow.die;
import static org.javarosa.xform.parse.Constants.ID_ATTR;
import static org.javarosa.xform.parse.Constants.NODESET_ATTR;
import static org.javarosa.xform.parse.Constants.RANK;
import static org.javarosa.xform.parse.Constants.SELECT;
import static org.javarosa.xform.parse.Constants.SELECTONE;
import static org.javarosa.xform.parse.RandomizeHelper.cleanNodesetDefinition;
import static org.javarosa.xform.parse.RandomizeHelper.cleanSeedDefinition;
import static org.javarosa.xform.parse.RangeParser.populateQuestionWithRangeAttributes;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import kotlin.Pair;
import org.javarosa.core.model.DataBinding;
import org.javarosa.core.model.FormDef;
Expand Down Expand Up @@ -73,49 +115,6 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableSet;
import static org.javarosa.core.model.Constants.CONTROL_AUDIO_CAPTURE;
import static org.javarosa.core.model.Constants.CONTROL_FILE_CAPTURE;
import static org.javarosa.core.model.Constants.CONTROL_IMAGE_CHOOSE;
import static org.javarosa.core.model.Constants.CONTROL_INPUT;
import static org.javarosa.core.model.Constants.CONTROL_OSM_CAPTURE;
import static org.javarosa.core.model.Constants.CONTROL_RANGE;
import static org.javarosa.core.model.Constants.CONTROL_RANK;
import static org.javarosa.core.model.Constants.CONTROL_SECRET;
import static org.javarosa.core.model.Constants.CONTROL_SELECT_MULTI;
import static org.javarosa.core.model.Constants.CONTROL_SELECT_ONE;
import static org.javarosa.core.model.Constants.CONTROL_TRIGGER;
import static org.javarosa.core.model.Constants.CONTROL_UPLOAD;
import static org.javarosa.core.model.Constants.CONTROL_VIDEO_CAPTURE;
import static org.javarosa.core.model.Constants.DATATYPE_CHOICE;
import static org.javarosa.core.model.Constants.DATATYPE_MULTIPLE_ITEMS;
import static org.javarosa.core.model.Constants.XFTAG_UPLOAD;
import static org.javarosa.core.services.ProgramFlow.die;
import static org.javarosa.xform.parse.Constants.ID_ATTR;
import static org.javarosa.xform.parse.Constants.NODESET_ATTR;
import static org.javarosa.xform.parse.Constants.RANK;
import static org.javarosa.xform.parse.Constants.SELECT;
import static org.javarosa.xform.parse.Constants.SELECTONE;
import static org.javarosa.xform.parse.RandomizeHelper.cleanNodesetDefinition;
import static org.javarosa.xform.parse.RandomizeHelper.cleanSeedDefinition;
import static org.javarosa.xform.parse.RangeParser.populateQuestionWithRangeAttributes;

/* droos: i think we need to start storing the contents of the <bind>s in the formdef again */

/**
Expand Down Expand Up @@ -2108,6 +2107,7 @@ public static TreeElement buildInstanceStructure(Element node, TreeElement paren
if (node.getAttributeCount() > 0) {
for (int i = 0; i < node.getAttributeCount(); i++) {
String attrNamespace = node.getAttributeNamespace(i);
String attrNamespacePrefix = namespacePrefixesByUri.get(attrNamespace);
String attrName = node.getAttributeName(i);
if (attrNamespace.equals(NAMESPACE_JAVAROSA) && attrName.equals("template")) {
continue;
Expand All @@ -2116,7 +2116,7 @@ public static TreeElement buildInstanceStructure(Element node, TreeElement paren
continue;
}

element.setAttribute(attrNamespace, attrName, node.getAttributeValue(i));
element.setAttribute(attrNamespace, attrNamespacePrefix, attrName, node.getAttributeValue(i));
}
}

Expand Down
Loading