anotherim/src/main/java/eu/siacs/conversations/xml/Element.java

219 lines
5.1 KiB
Java
Raw Normal View History

2014-10-22 16:38:44 +00:00
package eu.siacs.conversations.xml;
import org.jetbrains.annotations.NotNull;
2014-10-22 16:38:44 +00:00
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import eu.siacs.conversations.utils.XmlHelper;
import eu.siacs.conversations.xmpp.InvalidJid;
2020-05-15 15:06:16 +00:00
import eu.siacs.conversations.xmpp.Jid;
2021-01-23 08:25:34 +00:00
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
2014-10-22 16:38:44 +00:00
public class Element {
private final String name;
private Hashtable<String, String> attributes = new Hashtable<>();
private String content;
2014-11-06 19:10:03 +00:00
protected List<Element> children = new ArrayList<>();
2014-10-22 16:38:44 +00:00
public Element(String name) {
this.name = name;
}
public Element(String name, String xmlns) {
this.name = name;
this.setAttribute("xmlns", xmlns);
}
2014-10-22 16:38:44 +00:00
public Element addChild(Element child) {
this.content = null;
children.add(child);
return child;
}
public Element addChild(String name) {
this.content = null;
Element child = new Element(name);
children.add(child);
return child;
}
public Element addChild(String name, String xmlns) {
this.content = null;
Element child = new Element(name);
child.setAttribute("xmlns", xmlns);
children.add(child);
return child;
}
public Element setContent(String content) {
this.content = content;
this.children.clear();
return this;
}
public Element findChild(String name) {
for (Element child : this.children) {
if (child.getName().equals(name)) {
return child;
}
}
return null;
}
public String findChildContent(String name) {
Element element = findChild(name);
return element == null ? null : element.getContent();
}
show language in message bubble if multiple language variants were received XML and by inheritence XMPP has the feature of transmitting multiple language variants for the same content. This can be really useful if, for example, you are talking to an automated system. A chat bot could greet you in your own language. On the wire this will usually look like this: ```xml <message to="you"> <body>Good morning</body> <body xml:lang="de">Guten Morgen</body> </message> ``` However receiving such a message in a group chat can be very confusing and potentially dangerous if the sender puts conflicting information in there and different people get shown different strings. Disabeling support for localization entirely isn’t an ideal solution as on principle it is still a good feature; and other clients might still show a localization even if Conversations would always show the default language. So instead Conversations now shows the displayed language in a corner of the message bubble if more than one translation has been received. If multiple languages are received Conversations will attempt to find one in the language the operating system is set to. If no such translation can be found it will attempt to display the English string. If English can not be found either (for example a message that only has ru and fr on a phone that is set to de) it will display what ever language came first. Furthermore Conversations will discard (not show at all) messages with with multiple bodies of the same language. (This is considered an invalid message) The lanuage tag will not be shown if Conversations received a single body in a language not understood by the user. (For example operating system set to 'de' and message received with one body in 'ru' will just display that body as usual.) As a guide line to the user: If you are reading a message where it is important that this message is not interpreted differently by different people (like a vote (+1 / -1) in a chat room) make sure it has *no* language tag.
2019-09-12 08:12:47 +00:00
public LocalizedContent findInternationalizedChildContentInDefaultNamespace(String name) {
return LocalizedContent.get(this, name);
}
2014-10-22 16:38:44 +00:00
public Element findChild(String name, String xmlns) {
for (Element child : this.children) {
if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) {
2014-10-22 16:38:44 +00:00
return child;
}
2014-10-22 16:38:44 +00:00
}
return null;
}
public Element findChildEnsureSingle(String name, String xmlns) {
final List<Element> results = new ArrayList<>();
for (Element child : this.children) {
if (name.equals(child.getName()) && xmlns.equals(child.getAttribute("xmlns"))) {
results.add(child);
}
}
if (results.size() == 1) {
return results.get(0);
}
return null;
}
public String findChildContent(String name, String xmlns) {
Element element = findChild(name,xmlns);
return element == null ? null : element.getContent();
}
public boolean hasChild(final String name) {
2014-10-22 16:38:44 +00:00
return findChild(name) != null;
}
public boolean hasChild(final String name, final String xmlns) {
2014-10-22 16:38:44 +00:00
return findChild(name, xmlns) != null;
}
public List<Element> getChildren() {
return this.children;
}
public Element setChildren(List<Element> children) {
this.children = children;
return this;
}
public final String getContent() {
2014-10-22 16:38:44 +00:00
return content;
}
public Element setAttribute(String name, String value) {
if (name != null && value != null) {
this.attributes.put(name, value);
}
return this;
2020-05-15 15:06:16 +00:00
}
public Element setAttribute(String name, Jid value) {
if (name != null && value != null) {
this.attributes.put(name, value.toEscapedString());
}
return this;
2014-10-22 16:38:44 +00:00
}
2018-06-24 14:33:15 +00:00
public Element removeAttribute(String name) {
this.attributes.remove(name);
return this;
}
2014-10-22 16:38:44 +00:00
public Element setAttributes(Hashtable<String, String> attributes) {
this.attributes = attributes;
return this;
}
public String getAttribute(String name) {
if (this.attributes.containsKey(name)) {
return this.attributes.get(name);
} else {
return null;
}
}
public Jid getAttributeAsJid(String name) {
final String jid = this.getAttribute(name);
if (jid != null && !jid.isEmpty()) {
try {
2018-03-11 17:32:16 +00:00
return Jid.ofEscaped(jid);
2018-03-05 17:30:40 +00:00
} catch (final IllegalArgumentException e) {
return InvalidJid.of(jid, this instanceof MessagePacket);
}
}
return null;
}
2014-11-06 19:10:03 +00:00
2014-10-22 16:38:44 +00:00
public Hashtable<String, String> getAttributes() {
return this.attributes;
}
@NotNull
2014-10-22 16:38:44 +00:00
public String toString() {
final StringBuilder elementOutput = new StringBuilder();
2014-10-22 16:38:44 +00:00
if ((content == null) && (children.size() == 0)) {
Tag emptyTag = Tag.empty(name);
emptyTag.setAtttributes(this.attributes);
elementOutput.append(emptyTag.toString());
} else {
Tag startTag = Tag.start(name);
startTag.setAtttributes(this.attributes);
elementOutput.append(startTag);
if (content != null) {
elementOutput.append(XmlHelper.encodeEntities(content));
} else {
for (Element child : children) {
elementOutput.append(child.toString());
}
}
Tag endTag = Tag.end(name);
elementOutput.append(endTag);
}
return elementOutput.toString();
}
public final String getName() {
2014-10-22 16:38:44 +00:00
return name;
}
public void clearChildren() {
this.children.clear();
}
public void setAttribute(String name, long value) {
this.setAttribute(name, Long.toString(value));
}
public void setAttribute(String name, int value) {
this.setAttribute(name, Integer.toString(value));
}
2014-12-05 00:54:16 +00:00
public boolean getAttributeAsBoolean(String name) {
String attr = getAttribute(name);
return (attr != null && (attr.equalsIgnoreCase("true") || attr.equalsIgnoreCase("1")));
}
2015-12-04 21:03:46 +00:00
public String getNamespace() {
return getAttribute("xmlns");
}
2014-10-22 16:38:44 +00:00
}