Detailed changes
@@ -3,19 +3,21 @@ package eu.siacs.conversations.xml;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
+import java.util.stream.Collectors;
import eu.siacs.conversations.utils.XmlHelper;
import eu.siacs.conversations.xmpp.InvalidJid;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
-public class Element {
+public class Element implements Node {
private final String name;
private Hashtable<String, String> attributes = new Hashtable<>();
- private String content;
- protected List<Element> children = new ArrayList<>();
+ private List<Element> children = new ArrayList<>();
+ private List<Node> childNodes = new ArrayList<>();
public Element(String name) {
this.name = name;
@@ -26,30 +28,52 @@ public class Element {
this.setAttribute("xmlns", xmlns);
}
- public Element addChild(Element child) {
- this.content = null;
- children.add(child);
+ public Node prependChild(Node child) {
+ childNodes.add(0, child);
+ if (child instanceof Element) children.add(0, (Element) child);
+ return child;
+ }
+
+ public Node addChild(Node child) {
+ childNodes.add(child);
+ if (child instanceof Element) children.add((Element) child);
return child;
}
public Element addChild(String name) {
- this.content = null;
Element child = new Element(name);
+ childNodes.add(child);
children.add(child);
return child;
}
public Element addChild(String name, String xmlns) {
- this.content = null;
Element child = new Element(name);
child.setAttribute("xmlns", xmlns);
+ childNodes.add(child);
children.add(child);
return child;
}
+ public void addChildren(final Collection<? extends Node> children) {
+ if (children == null) return;
+
+ this.childNodes.addAll(children);
+ for (Node node : children) {
+ if (node instanceof Element) {
+ this.children.add((Element) node);
+ }
+ }
+ }
+
+ public void removeChild(Node child) {
+ this.childNodes.remove(child);
+ if (child instanceof Element) this.children.remove(child);
+ }
+
public Element setContent(String content) {
- this.content = content;
- this.children.clear();
+ clearChildren();
+ if (content != null) this.childNodes.add(new TextNode(content));
return this;
}
@@ -106,17 +130,18 @@ public class Element {
return findChild(name, xmlns) != null;
}
- public List<Element> getChildren() {
+ public final List<Element> getChildren() {
return this.children;
}
public Element setChildren(List<Element> children) {
+ this.childNodes = new ArrayList(children);
this.children = children;
return this;
}
public final String getContent() {
- return content;
+ return this.childNodes.stream().map(Node::getContent).filter(c -> c != null).collect(Collectors.joining());
}
public Element setAttribute(String name, String value) {
@@ -170,7 +195,7 @@ public class Element {
@NotNull
public String toString() {
final StringBuilder elementOutput = new StringBuilder();
- if ((content == null) && (children.size() == 0)) {
+ if (childNodes.size() == 0) {
Tag emptyTag = Tag.empty(name);
emptyTag.setAtttributes(this.attributes);
elementOutput.append(emptyTag.toString());
@@ -178,12 +203,8 @@ public class Element {
Tag startTag = Tag.start(name);
startTag.setAtttributes(this.attributes);
elementOutput.append(startTag);
- if (content != null) {
- elementOutput.append(XmlHelper.encodeEntities(content));
- } else {
- for (Element child : children) {
- elementOutput.append(child.toString());
- }
+ for (Node child : childNodes) {
+ elementOutput.append(child.toString());
}
Tag endTag = Tag.end(name);
elementOutput.append(endTag);
@@ -197,6 +218,7 @@ public class Element {
public void clearChildren() {
this.children.clear();
+ this.childNodes.clear();
}
public void setAttribute(String name, long value) {
@@ -23,7 +23,7 @@ public class LocalizedContent {
public static LocalizedContent get(final Element element, String name) {
final HashMap<String, String> contents = new HashMap<>();
final String parentLanguage = element.getAttribute("xml:lang");
- for(Element child : element.children) {
+ for(Element child : element.getChildren()) {
if (name.equals(child.getName())) {
final String namespace = child.getNamespace();
final String childLanguage = child.getAttribute("xml:lang");
@@ -0,0 +1,5 @@
+package eu.siacs.conversations.xml;
+
+public interface Node {
+ public String getContent();
+}
@@ -0,0 +1,20 @@
+package eu.siacs.conversations.xml;
+
+import eu.siacs.conversations.utils.XmlHelper;
+
+public class TextNode implements Node {
+ protected String content;
+
+ public TextNode(final String content) {
+ if (content == null) throw new IllegalArgumentException("null TextNode is not allowed");
+ this.content = content;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public String toString() {
+ return XmlHelper.encodeEntities(content);
+ }
+}
@@ -94,15 +94,10 @@ public class XmlReader implements Closeable {
if (nextTag == null) {
throw new IOException("interrupted mid tag");
}
- if (nextTag.isNo()) {
- element.setContent(nextTag.getName());
- nextTag = this.readTag();
- if (nextTag == null) {
- throw new IOException("interrupted mid tag");
- }
- }
while (!nextTag.isEnd(element.getName())) {
- if (!nextTag.isNo()) {
+ if (nextTag.isNo()) {
+ element.addChild(new TextNode(nextTag.getName()));
+ } else {
Element child = this.readElement(nextTag);
element.addChild(child);
}
@@ -4,8 +4,8 @@ import android.os.Bundle;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
+import java.util.stream.Collectors;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
@@ -77,12 +77,7 @@ public class Data extends Element {
}
private void removeUnnecessaryChildren() {
- for(Iterator<Element> iterator = this.children.iterator(); iterator.hasNext();) {
- Element element = iterator.next();
- if (!element.getName().equals("field") && !element.getName().equals("title")) {
- iterator.remove();
- }
- }
+ setChildren(getChildren().stream().filter(element -> element.getName().equals("field") || element.getName().equals("title")).collect(Collectors.toList()));
}
public static Data parse(Element element) {
@@ -2,8 +2,8 @@ package eu.siacs.conversations.xmpp.forms;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
+import java.util.stream.Collectors;
import eu.siacs.conversations.xml.Element;
@@ -23,24 +23,15 @@ public class Field extends Element {
}
public void setValue(String value) {
- this.children.clear();
- this.addChild("value").setContent(value);
+ setChildren(List.of(new Element("value").setContent(value)));
}
public void setValues(Collection<String> values) {
- this.children.clear();
- for(String value : values) {
- this.addChild("value").setContent(value);
- }
+ setChildren(values.stream().map(val -> new Element("value").setContent(val)).collect(Collectors.toList()));
}
public void removeNonValueChildren() {
- for(Iterator<Element> iterator = this.children.iterator(); iterator.hasNext();) {
- Element element = iterator.next();
- if (!element.getName().equals("value")) {
- iterator.remove();
- }
- }
+ setChildren(getChildren().stream().filter(element -> element.getName().equals("value")).collect(Collectors.toList()));
}
public static Field parse(Element element) {
@@ -29,7 +29,7 @@ public class Group extends Element {
public List<String> getIdentificationTags() {
final ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
- for (final Element child : this.children) {
+ for (final Element child : getChildren()) {
if ("content".equals(child.getName())) {
final String name = child.getAttribute("name");
if (name != null) {
@@ -15,7 +15,7 @@ public class Propose extends Element {
public List<GenericDescription> getDescriptions() {
final ImmutableList.Builder<GenericDescription> builder = new ImmutableList.Builder<>();
- for (final Element child : this.children) {
+ for (final Element child : getChildren()) {
if ("description".equals(child.getName())) {
final String namespace = child.getNamespace();
if (FileTransferDescription.NAMESPACES.contains(namespace)) {
@@ -66,7 +66,7 @@ public class RtpDescription extends GenericDescription {
public List<Source> getSources() {
final ImmutableList.Builder<Source> builder = new ImmutableList.Builder<>();
- for (final Element child : this.children) {
+ for (final Element child : getChildren()) {
if ("source".equals(child.getName()) && Namespace.JINGLE_RTP_SOURCE_SPECIFIC_MEDIA_ATTRIBUTES.equals(child.getNamespace())) {
builder.add(Source.upgrade(child));
}
@@ -76,7 +76,7 @@ public class RtpDescription extends GenericDescription {
public List<SourceGroup> getSourceGroups() {
final ImmutableList.Builder<SourceGroup> builder = new ImmutableList.Builder<>();
- for (final Element child : this.children) {
+ for (final Element child : getChildren()) {
if ("ssrc-group".equals(child.getName()) && Namespace.JINGLE_RTP_SOURCE_SPECIFIC_MEDIA_ATTRIBUTES.equals(child.getNamespace())) {
builder.add(SourceGroup.upgrade(child));
}
@@ -326,16 +326,8 @@ public class RtpDescription extends GenericDescription {
return null;
}
- public void addChildren(final List<Element> children) {
- if (children != null) {
- this.children.addAll(children);
- }
- }
-
public void addParameters(List<Parameter> parameters) {
- if (parameters != null) {
- this.children.addAll(parameters);
- }
+ addChildren(parameters);
}
}
@@ -442,7 +434,7 @@ public class RtpDescription extends GenericDescription {
public List<Parameter> getParameters() {
ImmutableList.Builder<Parameter> builder = new ImmutableList.Builder<>();
- for (Element child : this.children) {
+ for (Element child : getChildren()) {
if ("parameter".equals(child.getName())) {
builder.add(Parameter.upgrade(child));
}
@@ -512,7 +504,7 @@ public class RtpDescription extends GenericDescription {
public List<String> getSsrcs() {
ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
- for (Element child : this.children) {
+ for (Element child : getChildren()) {
if ("source".equals(child.getName())) {
final String ssrc = child.getAttribute("ssrc");
if (ssrc != null) {
@@ -610,10 +602,4 @@ public class RtpDescription extends GenericDescription {
}
return rtpDescription;
}
-
- private void addChildren(List<Element> elements) {
- if (elements != null) {
- this.children.addAll(elements);
- }
- }
}
@@ -22,15 +22,13 @@ public class MessagePacket extends AbstractAcknowledgeableStanza {
}
public void setBody(String text) {
- this.children.remove(findChild("body"));
- Element body = new Element("body");
- body.setContent(text);
- this.children.add(0, body);
+ removeChild(findChild("body"));
+ prependChild(new Element("body").setContent(text));
}
public void setAxolotlMessage(Element axolotlMessage) {
- this.children.remove(findChild("body"));
- this.children.add(0, axolotlMessage);
+ removeChild(findChild("body"));
+ prependChild(axolotlMessage);
}
public void setType(int type) {