Element.java

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