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 LocalizedContent findInternationalizedChildContentInDefaultNamespace(String name) {
 72        return LocalizedContent.get(this, name);
 73    }
 74
 75    public Element findChild(String name, String xmlns) {
 76        for (Element child : this.children) {
 77            if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) {
 78                return child;
 79            }
 80        }
 81        return null;
 82    }
 83
 84    public Element findChildEnsureSingle(String name, String xmlns) {
 85        final List<Element> results = new ArrayList<>();
 86        for (Element child : this.children) {
 87            if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) {
 88                results.add(child);
 89            }
 90        }
 91        if (results.size() == 1) {
 92            return results.get(0);
 93        }
 94        return null;
 95    }
 96
 97    public String findChildContent(String name, String xmlns) {
 98        Element element = findChild(name, xmlns);
 99        return element == null ? null : element.getContent();
100    }
101
102    public boolean hasChild(final String name) {
103        return findChild(name) != null;
104    }
105
106    public boolean hasChild(final String name, final String xmlns) {
107        return findChild(name, xmlns) != null;
108    }
109
110    public List<Element> getChildren() {
111        return this.children;
112    }
113
114    public Element setChildren(List<Element> children) {
115        this.children = children;
116        return this;
117    }
118
119    public final String getContent() {
120        return content;
121    }
122
123    public Element setAttribute(String name, String value) {
124        if (name != null && value != null) {
125            this.attributes.put(name, value);
126        }
127        return this;
128    }
129
130    public Element setAttribute(String name, Jid value) {
131        if (name != null && value != null) {
132            this.attributes.put(name, value.toString());
133        }
134        return this;
135    }
136
137    public void setAttribute(final String name, final boolean value) {
138        this.setAttribute(name, value ? "1" : "0");
139    }
140
141    public void removeAttribute(final String name) {
142        this.attributes.remove(name);
143    }
144
145    public Element setAttributes(Hashtable<String, String> attributes) {
146        this.attributes = attributes;
147        return this;
148    }
149
150    public String getAttribute(String name) {
151        if (this.attributes.containsKey(name)) {
152            return this.attributes.get(name);
153        } else {
154            return null;
155        }
156    }
157
158    public long getLongAttribute(final String name) {
159        final var value = Longs.tryParse(Strings.nullToEmpty(this.attributes.get(name)));
160        return value == null ? 0 : value;
161    }
162
163    public Optional<Integer> getOptionalIntAttribute(final String name) {
164        final String value = getAttribute(name);
165        if (value == null) {
166            return Optional.absent();
167        }
168        return Optional.fromNullable(Ints.tryParse(value));
169    }
170
171    public Jid getAttributeAsJid(final String name) {
172        final String jid = this.getAttribute(name);
173        if (Strings.isNullOrEmpty(jid)) {
174            return null;
175        }
176        return Jid.ofOrInvalid(jid, this instanceof Message);
177    }
178
179    public Hashtable<String, String> getAttributes() {
180        return this.attributes;
181    }
182
183    @NonNull
184    public String toString() {
185        final StringBuilder elementOutput = new StringBuilder();
186        if (content == null && children.isEmpty()) {
187            final Tag emptyTag = Tag.empty(name);
188            emptyTag.setAttributes(this.attributes);
189            elementOutput.append(emptyTag);
190        } else {
191            final Tag startTag = Tag.start(name);
192            startTag.setAttributes(this.attributes);
193            elementOutput.append(startTag);
194            if (content != null) {
195                elementOutput.append(XmlHelper.encodeEntities(content));
196            } else {
197                for (final Element child : children) {
198                    elementOutput.append(child.toString());
199                }
200            }
201            final Tag endTag = Tag.end(name);
202            elementOutput.append(endTag);
203        }
204        return elementOutput.toString();
205    }
206
207    public final String getName() {
208        return name;
209    }
210
211    public void clearChildren() {
212        this.children.clear();
213    }
214
215    public void setAttribute(String name, long value) {
216        this.setAttribute(name, Long.toString(value));
217    }
218
219    public void setAttribute(String name, int value) {
220        this.setAttribute(name, Integer.toString(value));
221    }
222
223    public boolean getAttributeAsBoolean(String name) {
224        String attr = getAttribute(name);
225        return (attr != null && (attr.equalsIgnoreCase("true") || attr.equalsIgnoreCase("1")));
226    }
227
228    public String getNamespace() {
229        return getAttribute("xmlns");
230    }
231}