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