Element.java

  1package eu.siacs.conversations.xml;
  2
  3import androidx.annotation.NonNull;
  4import com.google.common.base.Optional;
  5import com.google.common.base.Strings;
  6import com.google.common.primitives.Ints;
  7import com.google.common.primitives.Longs;
  8import eu.siacs.conversations.utils.XmlHelper;
  9import eu.siacs.conversations.xmpp.Jid;
 10import im.conversations.android.xmpp.model.stanza.Message;
 11import java.util.ArrayList;
 12import java.util.Hashtable;
 13import java.util.List;
 14
 15public class Element {
 16    private final String name;
 17    private Hashtable<String, String> attributes = new Hashtable<>();
 18    private String content;
 19    protected List<Element> children = new ArrayList<>();
 20
 21    public Element(String name) {
 22        this.name = name;
 23    }
 24
 25    public Element(String name, String xmlns) {
 26        this.name = name;
 27        this.setAttribute("xmlns", xmlns);
 28    }
 29
 30    public Element addChild(Element child) {
 31        this.content = null;
 32        children.add(child);
 33        return child;
 34    }
 35
 36    public Element addChild(String name) {
 37        this.content = null;
 38        Element child = new Element(name);
 39        children.add(child);
 40        return child;
 41    }
 42
 43    public Element addChild(String name, String xmlns) {
 44        this.content = null;
 45        Element child = new Element(name);
 46        child.setAttribute("xmlns", xmlns);
 47        children.add(child);
 48        return child;
 49    }
 50
 51    public Element setContent(String content) {
 52        this.content = content;
 53        this.children.clear();
 54        return this;
 55    }
 56
 57    public Element findChild(String name) {
 58        for (Element child : this.children) {
 59            if (child.getName().equals(name)) {
 60                return child;
 61            }
 62        }
 63        return null;
 64    }
 65
 66    public String findChildContent(String name) {
 67        Element element = findChild(name);
 68        return element == null ? null : element.getContent();
 69    }
 70
 71    public Element findChild(String name, String xmlns) {
 72        for (Element child : this.children) {
 73            if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) {
 74                return child;
 75            }
 76        }
 77        return null;
 78    }
 79
 80    public Element findChildEnsureSingle(String name, String xmlns) {
 81        final List<Element> results = new ArrayList<>();
 82        for (Element child : this.children) {
 83            if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) {
 84                results.add(child);
 85            }
 86        }
 87        if (results.size() == 1) {
 88            return results.get(0);
 89        }
 90        return null;
 91    }
 92
 93    public String findChildContent(String name, String xmlns) {
 94        Element element = findChild(name, xmlns);
 95        return element == null ? null : element.getContent();
 96    }
 97
 98    public boolean hasChild(final String name) {
 99        return findChild(name) != null;
100    }
101
102    public boolean hasChild(final String name, final String xmlns) {
103        return findChild(name, xmlns) != null;
104    }
105
106    public List<Element> getChildren() {
107        return this.children;
108    }
109
110    public Element setChildren(List<Element> children) {
111        this.children = children;
112        return this;
113    }
114
115    public final String getContent() {
116        return content;
117    }
118
119    public Element setAttribute(String name, String value) {
120        if (name != null && value != null) {
121            this.attributes.put(name, value);
122        }
123        return this;
124    }
125
126    public Element setAttribute(String name, Jid value) {
127        if (name != null && value != null) {
128            this.attributes.put(name, value.toString());
129        }
130        return this;
131    }
132
133    public void setAttribute(final String name, final boolean value) {
134        this.setAttribute(name, value ? "1" : "0");
135    }
136
137    public void removeAttribute(final String name) {
138        this.attributes.remove(name);
139    }
140
141    public Element setAttributes(Hashtable<String, String> attributes) {
142        this.attributes = attributes;
143        return this;
144    }
145
146    public String getAttribute(String name) {
147        if (this.attributes.containsKey(name)) {
148            return this.attributes.get(name);
149        } else {
150            return null;
151        }
152    }
153
154    public long getLongAttribute(final String name) {
155        final var value = Longs.tryParse(Strings.nullToEmpty(this.attributes.get(name)));
156        return value == null ? 0 : value;
157    }
158
159    public Optional<Integer> getOptionalIntAttribute(final String name) {
160        final String value = getAttribute(name);
161        if (value == null) {
162            return Optional.absent();
163        }
164        return Optional.fromNullable(Ints.tryParse(value));
165    }
166
167    public Jid getAttributeAsJid(final String name) {
168        final String jid = this.getAttribute(name);
169        if (Strings.isNullOrEmpty(jid)) {
170            return null;
171        }
172        return Jid.ofOrInvalid(jid, this instanceof Message);
173    }
174
175    public Hashtable<String, String> getAttributes() {
176        return this.attributes;
177    }
178
179    @NonNull
180    public String toString() {
181        final StringBuilder elementOutput = new StringBuilder();
182        if (content == null && children.isEmpty()) {
183            final Tag emptyTag = Tag.empty(name);
184            emptyTag.setAttributes(this.attributes);
185            elementOutput.append(emptyTag);
186        } else {
187            final Tag startTag = Tag.start(name);
188            startTag.setAttributes(this.attributes);
189            elementOutput.append(startTag);
190            if (content != null) {
191                elementOutput.append(XmlHelper.encodeEntities(content));
192            } else {
193                for (final Element child : children) {
194                    elementOutput.append(child.toString());
195                }
196            }
197            final Tag endTag = Tag.end(name);
198            elementOutput.append(endTag);
199        }
200        return elementOutput.toString();
201    }
202
203    public final String getName() {
204        return name;
205    }
206
207    public void clearChildren() {
208        this.children.clear();
209    }
210
211    public void setAttribute(String name, long value) {
212        this.setAttribute(name, Long.toString(value));
213    }
214
215    public void setAttribute(String name, int value) {
216        this.setAttribute(name, Integer.toString(value));
217    }
218
219    public boolean getAttributeAsBoolean(String name) {
220        String attr = getAttribute(name);
221        return (attr != null && (attr.equalsIgnoreCase("true") || attr.equalsIgnoreCase("1")));
222    }
223
224    public String getNamespace() {
225        return getAttribute("xmlns");
226    }
227}