mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-12-08 12:01:09 +01:00
Treat <body/> just like all other extension elements in Message
This turned out to be a rather large change.
This commit is contained in:
parent
cb9a11b74e
commit
a9e45475ab
39 changed files with 261 additions and 219 deletions
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.jivesoftware.smack.packet;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.jivesoftware.smack.util.Objects;
|
||||
|
|
@ -128,7 +129,7 @@ public abstract class IQ extends Stanza {
|
|||
public final XmlStringBuilder toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder buf = new XmlStringBuilder(enclosingNamespace);
|
||||
buf.halfOpenElement(IQ_ELEMENT);
|
||||
addCommonAttributes(buf);
|
||||
addCommonAttributes(buf, enclosingNamespace);
|
||||
if (type == null) {
|
||||
buf.attribute("type", "get");
|
||||
}
|
||||
|
|
@ -158,9 +159,10 @@ public abstract class IQ extends Stanza {
|
|||
IQChildElementXmlStringBuilder iqChildElement = getIQChildElementBuilder(new IQChildElementXmlStringBuilder(this));
|
||||
if (iqChildElement != null) {
|
||||
xml.append(iqChildElement);
|
||||
XmlStringBuilder extensionsXml = getExtensionsXML();
|
||||
|
||||
List<ExtensionElement> extensionsXml = getExtensions();
|
||||
if (iqChildElement.isEmptyElement) {
|
||||
if (extensionsXml.length() == 0) {
|
||||
if (extensionsXml.isEmpty()) {
|
||||
xml.closeEmptyElement();
|
||||
return xml;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
private String thread = null;
|
||||
|
||||
private final Set<Subject> subjects = new HashSet<Subject>();
|
||||
private final Set<Body> bodies = new HashSet<Body>();
|
||||
|
||||
/**
|
||||
* Creates a new, "normal" message.
|
||||
|
|
@ -142,7 +141,6 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
this.type = other.type;
|
||||
this.thread = other.thread;
|
||||
this.subjects.addAll(other.subjects);
|
||||
this.bodies.addAll(other.bodies);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -197,7 +195,7 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
private Subject getMessageSubject(String language) {
|
||||
language = determineLanguage(language);
|
||||
for (Subject subject : subjects) {
|
||||
if (language.equals(subject.language)) {
|
||||
if (Objects.equals(language, subject.language)) {
|
||||
return subject;
|
||||
}
|
||||
}
|
||||
|
|
@ -296,7 +294,7 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
* @return the body of the message.
|
||||
*/
|
||||
public String getBody() {
|
||||
return getBody(null);
|
||||
return getBody(language);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -331,7 +329,13 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
* @since 3.0.2
|
||||
*/
|
||||
public Set<Body> getBodies() {
|
||||
return Collections.unmodifiableSet(bodies);
|
||||
List<ExtensionElement> bodiesList = getExtensions(Body.ELEMENT, Body.NAMESPACE);
|
||||
Set<Body> resultSet = new HashSet<>(bodiesList.size());
|
||||
for (ExtensionElement extensionElement : bodiesList) {
|
||||
Body body = (Body) extensionElement;
|
||||
resultSet.add(body);
|
||||
}
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -375,8 +379,11 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
*/
|
||||
public Body addBody(String language, String body) {
|
||||
language = determineLanguage(language);
|
||||
|
||||
removeBody(language);
|
||||
|
||||
Body messageBody = new Body(language, body);
|
||||
bodies.add(messageBody);
|
||||
addExtension(messageBody);
|
||||
return messageBody;
|
||||
}
|
||||
|
||||
|
|
@ -406,7 +413,8 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
* @since 3.0.2
|
||||
*/
|
||||
public boolean removeBody(Body body) {
|
||||
return bodies.remove(body);
|
||||
ExtensionElement removedElement = removeExtension(body);
|
||||
return removedElement != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -418,7 +426,7 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
public List<String> getBodyLanguages() {
|
||||
Body defaultBody = getMessageBody(null);
|
||||
List<String> languages = new ArrayList<String>();
|
||||
for (Body body : bodies) {
|
||||
for (Body body : getBodies()) {
|
||||
if (!body.equals(defaultBody)) {
|
||||
languages.add(body.language);
|
||||
}
|
||||
|
|
@ -472,9 +480,9 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
|
||||
@Override
|
||||
public XmlStringBuilder toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder buf = new XmlStringBuilder();
|
||||
XmlStringBuilder buf = new XmlStringBuilder(enclosingNamespace);
|
||||
buf.halfOpenElement(ELEMENT);
|
||||
addCommonAttributes(buf);
|
||||
enclosingNamespace = addCommonAttributes(buf, enclosingNamespace);
|
||||
buf.optAttribute("type", type);
|
||||
buf.rightAngleBracket();
|
||||
|
||||
|
|
@ -490,25 +498,15 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
|
|||
continue;
|
||||
buf.append(subject.toXML(null));
|
||||
}
|
||||
// Add the body in the default language
|
||||
Body defaultBody = getMessageBody(null);
|
||||
if (defaultBody != null) {
|
||||
buf.element("body", defaultBody.message);
|
||||
}
|
||||
// Add the bodies in other languages
|
||||
for (Body body : getBodies()) {
|
||||
// Skip the default language
|
||||
if (body.equals(defaultBody))
|
||||
continue;
|
||||
buf.append(body.toXML(enclosingNamespace));
|
||||
}
|
||||
buf.optElement("thread", thread);
|
||||
// Append the error subpacket if the message type is an error.
|
||||
if (type == Type.error) {
|
||||
appendErrorIfExists(buf);
|
||||
}
|
||||
// Add packet extensions, if any are defined.
|
||||
buf.append(getExtensionsXML());
|
||||
|
||||
// Add extension elements, if any are defined.
|
||||
buf.append(getExtensions(), enclosingNamespace);
|
||||
|
||||
buf.closeElement(ELEMENT);
|
||||
return buf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,9 +273,9 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
|||
|
||||
@Override
|
||||
public XmlStringBuilder toXML(String enclosingNamespace) {
|
||||
XmlStringBuilder buf = new XmlStringBuilder();
|
||||
XmlStringBuilder buf = new XmlStringBuilder(enclosingNamespace);
|
||||
buf.halfOpenElement(ELEMENT);
|
||||
addCommonAttributes(buf);
|
||||
addCommonAttributes(buf, enclosingNamespace);
|
||||
if (type != Type.available) {
|
||||
buf.attribute("type", type);
|
||||
}
|
||||
|
|
@ -288,7 +288,8 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
|||
if (mode != null && mode != Mode.available) {
|
||||
buf.element("show", mode);
|
||||
}
|
||||
buf.append(getExtensionsXML());
|
||||
|
||||
buf.append(getExtensions(), enclosingNamespace);
|
||||
|
||||
// Add the error sub-packet, if there is one.
|
||||
appendErrorIfExists(buf);
|
||||
|
|
|
|||
|
|
@ -470,7 +470,15 @@ public abstract class Stanza implements TopLevelStreamElement {
|
|||
* @return the removed stanza extension or null.
|
||||
*/
|
||||
public ExtensionElement removeExtension(ExtensionElement extension) {
|
||||
return removeExtension(extension.getElementName(), extension.getNamespace());
|
||||
String key = XmppStringUtils.generateKey(extension.getElementName(), extension.getNamespace());
|
||||
synchronized (packetExtensions) {
|
||||
List<ExtensionElement> list = packetExtensions.getAll(key);
|
||||
boolean removed = list.remove(extension);
|
||||
if (removed) {
|
||||
return extension;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -479,22 +487,6 @@ public abstract class Stanza implements TopLevelStreamElement {
|
|||
@Override
|
||||
public abstract String toString();
|
||||
|
||||
/**
|
||||
* Returns the extension sub-packets (including properties data) as an XML
|
||||
* String, or the Empty String if there are no stanza extensions.
|
||||
*
|
||||
* @return the extension sub-packets as XML or the Empty String if there
|
||||
* are no stanza extensions.
|
||||
*/
|
||||
protected final XmlStringBuilder getExtensionsXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder();
|
||||
// Add in all standard extension sub-packets.
|
||||
for (ExtensionElement extension : getExtensions()) {
|
||||
xml.append(extension.toXML(null));
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default language used for all messages containing localized content.
|
||||
*
|
||||
|
|
@ -507,13 +499,26 @@ public abstract class Stanza implements TopLevelStreamElement {
|
|||
/**
|
||||
* Add to, from, id and 'xml:lang' attributes
|
||||
*
|
||||
* @param xml
|
||||
* @param xml the {@link XmlStringBuilder}.
|
||||
* @param enclosingNamespace the enclosing XML namespace.
|
||||
* @return the set namespace for this stanza.
|
||||
*/
|
||||
protected void addCommonAttributes(XmlStringBuilder xml) {
|
||||
protected String addCommonAttributes(XmlStringBuilder xml, String enclosingNamespace) {
|
||||
String namespace;
|
||||
if (enclosingNamespace == null || !enclosingNamespace.equals(StreamOpen.CLIENT_NAMESPACE)
|
||||
|| !enclosingNamespace.equals(StreamOpen.SERVER_NAMESPACE)) {
|
||||
namespace = StreamOpen.CLIENT_NAMESPACE;
|
||||
} else {
|
||||
namespace = enclosingNamespace;
|
||||
}
|
||||
|
||||
xml.xmlnsAttribute(namespace);
|
||||
xml.optAttribute("to", getTo());
|
||||
xml.optAttribute("from", getFrom());
|
||||
xml.optAttribute("id", getStanzaId());
|
||||
xml.xmllangAttribute(getLanguage());
|
||||
|
||||
return namespace;
|
||||
}
|
||||
|
||||
protected void logCommonAttributes(StringBuilder sb) {
|
||||
|
|
|
|||
|
|
@ -246,28 +246,12 @@ public class PacketParserUtils {
|
|||
switch (elementName) {
|
||||
case "subject":
|
||||
String xmlLangSubject = getLanguageAttribute(parser);
|
||||
if (xmlLangSubject == null) {
|
||||
xmlLangSubject = defaultLanguage;
|
||||
}
|
||||
|
||||
String subject = parseElementText(parser);
|
||||
|
||||
if (message.getSubject(xmlLangSubject) == null) {
|
||||
message.addSubject(xmlLangSubject, subject);
|
||||
}
|
||||
break;
|
||||
case Message.BODY:
|
||||
String xmlLang = getLanguageAttribute(parser);
|
||||
if (xmlLang == null) {
|
||||
xmlLang = defaultLanguage;
|
||||
}
|
||||
|
||||
String body = parseElementText(parser);
|
||||
|
||||
if (message.getBody(xmlLang) == null) {
|
||||
message.addBody(xmlLang, body);
|
||||
}
|
||||
break;
|
||||
case "thread":
|
||||
if (thread == null) {
|
||||
thread = parser.nextText();
|
||||
|
|
@ -290,6 +274,11 @@ public class PacketParserUtils {
|
|||
}
|
||||
|
||||
message.setThread(thread);
|
||||
|
||||
// TODO check for duplicate body elements. This means we need to check for duplicate xml:lang pairs and for
|
||||
// situations where we have a body element with an explicit xml lang set and once where the value is inherited
|
||||
// and both values are equal.
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -457,8 +457,12 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
|
|||
}
|
||||
|
||||
public XmlStringBuilder append(Collection<? extends Element> elements) {
|
||||
return append(elements, null);
|
||||
}
|
||||
|
||||
public XmlStringBuilder append(Collection<? extends Element> elements, String enclosingNamespace) {
|
||||
for (Element element : elements) {
|
||||
append(element.toXML(null));
|
||||
append(element.toXML(enclosingNamespace));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue