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