Created
August 29, 2017 08:09
-
-
Save soulfly/4be1fac6177fb8993862fa5efa223f3a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.quickblox.chat.model; | |
import android.text.TextUtils; | |
import com.quickblox.chat.propertyparsers.MessagePropertyParser; | |
import org.jivesoftware.smack.SmackException; | |
import org.jivesoftware.smack.packet.ExtensionElement; | |
import org.jivesoftware.smack.provider.ExtensionElementProvider; | |
import org.jivesoftware.smack.util.XmlStringBuilder; | |
import org.xmlpull.v1.XmlPullParser; | |
import org.xmlpull.v1.XmlPullParserException; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Map; | |
/** | |
* This class provides a simple representation of additional custom parameters of chat message. Each element | |
* is a key in a Map with its CDATA being the value. | |
*/ | |
public class QBChatMessageExtension implements ExtensionElement { | |
public static final String ELEMENT_NAME = "extraParams"; | |
public static final String NAMESPACE = "jabber:client"; | |
public static final String TAG_ATTACHMENT = "attachment"; | |
public static final String ATTRIBUTE_NAME = "name"; | |
public static final String ATTRIBUTE_TYPE = "type"; | |
public static final String ATTRIBUTE_ID = "id"; | |
public static final String ATTRIBUTE_URL = "url"; | |
public static final String ATTRIBUTE_DATA = "data"; | |
public static final String ATTRIBUTE_CONTENT_TYPE = "content-type"; | |
public static final String ATTRIBUTE_SIZE = "size"; | |
public static final String ATTRIBUTE_WIDTH = "width"; | |
public static final String ATTRIBUTE_HEIGHT = "height"; | |
public static final String ATTRIBUTE_DURATION = "duration"; | |
private static Map<String, MessagePropertyParser<?>> complexPropertyParsers = new HashMap<>(); | |
private Map<String, String> properties; | |
/** | |
* Added for capability to add in message properties complex objects | |
*/ | |
private volatile Map<String, Object> complexPropertiesMap; | |
private List<QBAttachment> attachments; | |
QBChatMessageExtension() { | |
properties = new HashMap<>(); | |
attachments = new ArrayList<>(); | |
} | |
QBChatMessageExtension(Map<String, String> properties, List<QBAttachment> attachments, Map<String, Object> complexProperties) { | |
this.properties = properties; | |
this.attachments = attachments; | |
this.complexPropertiesMap = complexProperties; | |
} | |
public static void registerComplexPropertyParser(String elementName, MessagePropertyParser<?> propertyParser){ | |
complexPropertyParsers.put(elementName, propertyParser); | |
} | |
@Override | |
public String getElementName() { | |
return ELEMENT_NAME; | |
} | |
@Override | |
public String getNamespace() { | |
return NAMESPACE; | |
} | |
@Override | |
public CharSequence toXML() { | |
XmlStringBuilder buf = new XmlStringBuilder(); | |
buf.halfOpenElement(ELEMENT_NAME).xmlnsAttribute(NAMESPACE).rightAngleBracket(); | |
for (QBAttachment attachment : attachments) { | |
buf.halfOpenElement(TAG_ATTACHMENT); | |
buf.attribute(ATTRIBUTE_TYPE, attachment.getType()); | |
if (attachment.getName() != null) { | |
buf.attribute(ATTRIBUTE_NAME, attachment.getName()); | |
} | |
if (attachment.getId() != null) { | |
buf.attribute(ATTRIBUTE_ID, String.valueOf(attachment.getId())); | |
} | |
if (attachment.getUrl() != null) { | |
buf.attribute(ATTRIBUTE_URL, attachment.getUrl()); | |
} | |
if (attachment.getData() != null){ | |
buf.attribute(ATTRIBUTE_DATA, attachment.getData()); | |
} | |
if (attachment.getContentType() != null) { | |
buf.attribute(ATTRIBUTE_CONTENT_TYPE, attachment.getContentType()); | |
} | |
if (attachment.getSize() != 0) { | |
buf.attribute(ATTRIBUTE_SIZE, String.valueOf(attachment.getSize())); | |
} | |
if (attachment.getWidth() != 0) { | |
buf.attribute(ATTRIBUTE_WIDTH, String.valueOf(attachment.getWidth())); | |
} | |
if (attachment.getHeight() != 0) { | |
buf.attribute(ATTRIBUTE_HEIGHT, String.valueOf(attachment.getHeight())); | |
} | |
if (attachment.getDuration() != 0) { | |
buf.attribute(ATTRIBUTE_DURATION, String.valueOf(attachment.getDuration())); | |
} | |
buf.rightAngleBracket(); | |
buf.closeElement(TAG_ATTACHMENT); | |
} | |
// Add property | |
for (String name : getPropertyNames()) { | |
String value = getProperty(name); | |
buf.element(name, value); | |
} | |
// Add complex property | |
if( complexPropertiesMap != null) { | |
for (String key : complexPropertiesMap.keySet()) { | |
Object currentObject = complexPropertiesMap.get(key); | |
MessagePropertyParser<?> messagePropertyParser = complexPropertyParsers.get(key); | |
// if parser for object exists | |
if (messagePropertyParser != null) { | |
buf.append(messagePropertyParser.parseToXML(currentObject)); | |
} | |
} | |
} | |
buf.closeElement(ELEMENT_NAME); | |
return buf; | |
} | |
public void addAttachments(Collection<QBAttachment> attachments) { | |
this.attachments.addAll(attachments); | |
} | |
public Collection<QBAttachment> getAttachments() { | |
return Collections.unmodifiableList(attachments); | |
} | |
public String getProperty(String name) { | |
return properties.get(name); | |
} | |
public Object getComplexProperty(String name){ | |
return complexPropertiesMap.get(name); | |
} | |
public void setProperty(String name, String value) { | |
properties.put(name, value); | |
} | |
public void setComplexProperty(Map <String, Object> complexProperties) { | |
complexPropertiesMap = complexProperties; | |
} | |
public void setProperties(Map<String, String> properties) { | |
this.properties.putAll(properties); | |
} | |
private Collection<String> getPropertyNames() { | |
return Collections.unmodifiableSet(new HashSet<String>(properties.keySet())); | |
} | |
public Map<String, String> getProperties() { | |
return properties; | |
} | |
public static class Provider extends ExtensionElementProvider<QBChatMessageExtension> { | |
private XmlPullParser parser; | |
private List<QBAttachment> attachments; | |
private Map<String, String> properties; | |
private Map<String, Object> complexProperties; | |
@Override | |
public QBChatMessageExtension parse(XmlPullParser parser, int Depth) throws XmlPullParserException, IOException, SmackException { | |
this.parser = parser; | |
attachments = new ArrayList<>(); | |
properties = new HashMap<>(); | |
complexProperties = new HashMap<>(); | |
int tag = parser.next(); | |
while (isNotLastElement(tag)) { | |
if (isWhitespaceText(tag)){ | |
tag = parser.next(); | |
} else if (isAttachmentElement(tag)) { | |
parseAttachment(); | |
tag = parser.next(); | |
} else if (isPropertyStartElement(tag)) { | |
// Parser moves next method calls in parseProperty method | |
// in case of internal child exists in this property element | |
tag = parseProperty(); | |
} else if (isPropertyEndElement(tag)){ | |
tag = parser.next(); | |
} | |
} | |
return new QBChatMessageExtension(properties, attachments, complexProperties); | |
} | |
private boolean isNotLastElement(int tag) { | |
return !isLastElement(tag); | |
} | |
private boolean isLastElement(int tag) { | |
return (((tag == XmlPullParser.END_TAG) && parser.getName().equals( | |
QBChatMessageExtension.ELEMENT_NAME)) || tag == XmlPullParser.END_DOCUMENT); | |
} | |
private boolean isPropertyStartElement(int tag) { | |
return tag == XmlPullParser.START_TAG && isNotRootElement(); | |
} | |
private boolean isPropertyEndElement(int tag) { | |
return tag == XmlPullParser.END_TAG && isNotRootElement(); | |
} | |
private boolean isWhitespaceText(int tag) throws XmlPullParserException { | |
return (tag == XmlPullParser.TEXT && parser.isWhitespace()); | |
} | |
private boolean isNotRootElement() { | |
return !parser.getName().equals(QBChatMessageExtension.ELEMENT_NAME); | |
} | |
private boolean isAttachmentElement(int tag) { | |
return (tag == XmlPullParser.START_TAG) && parser.getName().equals( | |
QBChatMessageExtension.TAG_ATTACHMENT); | |
} | |
private void parseAttachment() { | |
String attachmentId = parser.getAttributeValue(null, QBChatMessageExtension.ATTRIBUTE_ID); | |
String attachmentType = parser.getAttributeValue(null, QBChatMessageExtension.ATTRIBUTE_TYPE); | |
String attachmentUrl = parser.getAttributeValue(null, QBChatMessageExtension.ATTRIBUTE_URL); | |
String attachmentData = parser.getAttributeValue(null, QBChatMessageExtension.ATTRIBUTE_DATA); | |
double attachmentSize = parseDouble(QBChatMessageExtension.ATTRIBUTE_SIZE); | |
int attachmentWidth = parseInt(QBChatMessageExtension.ATTRIBUTE_WIDTH); | |
int attachmentHeight = parseInt(QBChatMessageExtension.ATTRIBUTE_HEIGHT); | |
int attachmentDuration = parseInt(QBChatMessageExtension.ATTRIBUTE_DURATION); | |
String attachmentName = parser.getAttributeValue(null, QBChatMessageExtension.ATTRIBUTE_NAME); | |
String attachmentContentType = parser.getAttributeValue(null, QBChatMessageExtension.ATTRIBUTE_CONTENT_TYPE); | |
QBAttachment attachment = new QBAttachment(attachmentType); | |
if (attachmentId != null) { | |
attachment.setId(attachmentId); | |
} | |
attachment.setData(attachmentData); | |
attachment.setUrl(attachmentUrl); | |
attachment.setSize(attachmentSize); | |
attachment.setWidth(attachmentWidth); | |
attachment.setHeight(attachmentHeight); | |
attachment.setDuration(attachmentDuration); | |
attachment.setName(attachmentName); | |
attachment.setContentType(attachmentContentType); | |
attachments.add(attachment); | |
} | |
private int parseProperty() throws XmlPullParserException, IOException { | |
String name = parser.getName(); | |
MessagePropertyParser<?> complexParser = null; | |
if ((complexParser = complexPropertyParsers.get(name)) != null){ | |
Object object = parseComplexProperty(parser, complexParser); | |
complexProperties.put(name, object); | |
return parser.getEventType(); | |
} else { | |
int tag = parser.next(); | |
if (tag == XmlPullParser.TEXT) { | |
String value = parser.getText(); | |
properties.put(name, value); | |
// Move to END_TAG element | |
parser.next(); | |
} else { | |
skipCurrentComplexTag(name); | |
} | |
} | |
return parser.getEventType(); | |
} | |
private void skipCurrentComplexTag(String closeTagName) { | |
int tag = 0; | |
String currentTagName = ""; | |
do { | |
try { | |
tag = parser.next(); | |
currentTagName = parser.getName(); | |
} catch (XmlPullParserException e) { | |
e.printStackTrace(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} while (! (XmlPullParser.END_TAG == tag && closeTagName.equals(currentTagName))); | |
} | |
private Object parseComplexProperty(XmlPullParser parser, MessagePropertyParser<?> propertyParser) { | |
return propertyParser.parseFromXML(parser); | |
} | |
private int parseInt(String attributeName){ | |
int result = 0; | |
String strValue = parser.getAttributeValue(null, attributeName); | |
if (!TextUtils.isEmpty(strValue)) { | |
try { | |
result = Integer.parseInt(strValue); | |
} catch (NumberFormatException e){ | |
e.printStackTrace(); | |
} | |
} | |
return result; | |
} | |
private double parseDouble(String attributeName){ | |
double result = 0; | |
String strValue = parser.getAttributeValue(null, attributeName); | |
if (!TextUtils.isEmpty(strValue)) { | |
try { | |
result = Double.parseDouble(strValue); | |
} catch (NumberFormatException e){ | |
e.printStackTrace(); | |
} | |
} | |
return result; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment