package org.deviceconnect.android.uiapp.utils;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ClickableSpan;
import android.view.View;
import org.deviceconnect.message.DConnectMessage;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class MessageParser {
private final SpannableStringBuilder builder = new SpannableStringBuilder();
private boolean mFirstKey;
private int mParseInArray;
private int mFirstArrayValue;
private int mIndent;
private boolean mUriFlag;
private int indent;
private OnClickLinkListener mClickLinkListener;
public void setClickLinkListener(OnClickLinkListener clickLinkListener) {
mClickLinkListener = clickLinkListener;
}
public SpannableStringBuilder parse(final DConnectMessage message, int indent) {
if (message == null) {
throw new NullPointerException("message is null");
}
this.indent = indent;
startParse();
parseObject(message);
endParse();
return builder;
}
private void startParse() {
}
private void onKey(final String key) {
if (!mFirstKey) {
builder.append(",");
}
appendIndentSpace();
mUriFlag = key.equals("uri");
mFirstKey = false;
builder.append("\"");
builder.append(key);
builder.append("\"");
builder.append(":");
}
private void onValue(final Object value) {
if ((mParseInArray & (1 << mIndent)) != 0) {
if ((mFirstArrayValue & (1 << mIndent)) != 0) {
builder.append(",");
}
appendIndentSpace();
}
mFirstArrayValue |= (1 << mIndent);
if (Integer.class.isInstance(value)
|| Float.class.isInstance(value)
|| Double.class.isInstance(value)
|| Long.class.isInstance(value)
|| Byte.class.isInstance(value)
|| Short.class.isInstance(value)
|| Boolean.class.isInstance(value)) {
builder.append(String.valueOf(value));
} else if (value == null) {
builder.append("null");
} else if (String.class.isInstance(value)) {
builder.append("\"");
builder.append(String.valueOf(value));
builder.append("\"");
if (mUriFlag) {
final String uri = (String) value;
builder.setSpan(new ClickableSpan() {
@Override
public void onClick(final View widget) {
if (mClickLinkListener != null) {
mClickLinkListener.onClick(uri);
}
}
}, builder.length() - uri.getBytes().length - 1, builder.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else {
builder.append("\"");
builder.append(String.valueOf(value));
builder.append("\"");
}
mUriFlag = false;
}
private void startMap() {
appendIndentSpace();
builder.append("{");
mFirstKey = true;
mIndent++;
}
private void endMap() {
mFirstArrayValue &= ~(1 << mIndent);
mIndent--;
mFirstArrayValue |= (1 << mIndent);
appendIndentSpace();
builder.append("}");
}
private void startArray() {
mIndent++;
if ((mFirstArrayValue & (1 << mIndent)) != 0) {
builder.append(",");
}
mParseInArray |= (1 << mIndent);
builder.append("[");
}
private void endArray() {
mParseInArray &= ~(1 << mIndent);
mFirstArrayValue &= ~(1 << mIndent);
mIndent--;
mFirstArrayValue |= (1 << mIndent);
appendIndentSpace();
builder.append("]");
}
private void endParse() {
}
private void appendIndentSpace() {
if (indent <= 0) {
return;
}
if (builder.length() > 0) {
appendBreakLine();
}
for (int i = 0; i < mIndent * indent; i++) {
builder.append(" ");
}
}
private void appendBreakLine() {
if (indent <= 0) {
return;
}
builder.append("\n");
}
@SuppressWarnings("unchecked")
private Set<String> getKeySet(final Object message) {
Set<String> keySet = null;
if (message instanceof Map) {
keySet = ((Map<String, Object>) message).keySet();
}
return keySet;
}
@SuppressWarnings("unchecked")
private Object getValue(final Object message, final String key) {
return ((Map<String, Object>) message).get(key);
}
private boolean isArray(final Object value) {
return (value instanceof List);
}
private boolean isMap(final Object value) {
return (value instanceof Map);
}
private List<?> toArray(final Object value) {
return (List<?>) value;
}
/**
* オブジェクトをパースする.
*
* @param object オブジェクト
*/
private void parseObject(final Object object) {
if (isMap(object)) {
startMap();
for (String key : getKeySet(object)) {
onKey(key);
parseObject(getValue(object, key));
}
endMap();
} else if (isArray(object)) {
startArray();
for (Object obj : toArray(object)) {
parseObject(obj);
}
endArray();
} else {
onValue(object);
}
}
public interface OnClickLinkListener {
void onClick(final String uri);
}
}