package com.yunkapay.push.mobile.parcelable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import com.yunkapay.push.mobile.util.Logger;
import java.lang.reflect.*;
import java.util.*;
public abstract class GlobalParcelable<T extends GlobalParcelable> implements Parcelable {
public GlobalParcelable() {
// TODO Auto-generated constructor stub
}
public GlobalParcelable(Parcel in) {
String className = in.readString();
Log.i("GlobalParcelable", "Constructor: " + ((Object) this).getClass().getSimpleName() + "; In parcel: " + className);
readFromParcel(in);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(((Object) this).getClass().getName());
try {
dehydrate(this, dest);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void readFromParcel(Parcel in) {
try {
rehydrate(this, in);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
// writes fields of a GlobalParcelable to a parcel
// does not include the first parcelled item -- the class name
protected void dehydrate(GlobalParcelable model, Parcel out) throws IllegalArgumentException, IllegalAccessException {
Class<?> cla = ((Object) model).getClass();
Log.i("GlobalParcelable", "dehydrating... " + cla.toString());
// get the fields
Field[] fields=getFields(cla);
// sort the fields so it is in deterministic order
Arrays.sort(fields, compareMemberByName);
// populate the fields
for (Field field : fields) {
field.setAccessible(true);
int modifier = field.getModifiers();
Log.i("GlobalParcelable", "Field:" + field.getName() + " " + Modifier.isStatic(modifier) + " " + Modifier.isFinal(modifier));
if (field.getType().equals(int.class)) {
out.writeInt(field.getInt(model));
} else if (field.getType().equals(double.class)) {
out.writeDouble(field.getDouble(model));
} else if (field.getType().equals(float.class)) {
out.writeFloat(field.getFloat(model));
} else if (field.getType().equals(long.class)) {
out.writeLong(field.getLong(model));
} else if (field.getType().equals(String.class)) {
out.writeString((String) field.get(model));
} else if (field.getType().equals(boolean.class)) {
out.writeByte(field.getBoolean(model) ? (byte) 1 : (byte) 0);
} else if (field.getType().equals(Date.class)) {
Date date = (Date) field.get(model);
if (date != null) {
out.writeLong(date.getTime());
} else {
out.writeLong(0);
}
} else if (GlobalParcelable.class.isAssignableFrom(field.getType())) {
// why did this happen?
Log.e("GlobalParcelable", "GlobalParcelable F*ck up: " + " (" + field.getType().toString() + ")");
out.writeParcelable((GlobalParcelable) field.get(model), 0);
} else {
// wtf
Log.e("GlobalParcelable", "Could not write field to parcel: " + " (" + field.getType().toString() + ")");
}
}
}
protected static Field[] getFields(Class<?> cla) {
List<Field> fieldList = new ArrayList<Field>();
do {
Logger.d("Class "+cla.toString());
Field[] fields = cla.getDeclaredFields();
for (Field f : fields) {
int modifier = f.getModifiers();
if (Modifier.isStatic(modifier) && Modifier.isFinal(modifier)) {
Logger.d("final static value "+f.getName());
} else {
fieldList.add(f);
}
}
cla = cla.getSuperclass();
} while (cla != null && !GlobalParcelable.class.equals(cla));
return fieldList.toArray(new Field[fieldList.size()]);
}
// reads the parcelled items and put them into this object's fields
// must be run after getting the first parcelled item -- the class name
protected static void rehydrate(GlobalParcelable model, Parcel in) throws IllegalArgumentException, IllegalAccessException {
Class<?> cla = ((Object) model).getClass();
Log.i("GlobalParcelable", "rehydrating... " + cla.toString());
// get the fields
Field[] fields =getFields(cla);
// sort the fields so it is in deterministic order
Arrays.sort(fields, compareMemberByName);
// populate the fields
for (Field field : fields) {
field.setAccessible(true);
if (field.getType().equals(int.class)) {
field.set(model, in.readInt());
} else if (field.getType().equals(double.class)) {
field.set(model, in.readDouble());
} else if (field.getType().equals(float.class)) {
field.set(model, in.readFloat());
} else if (field.getType().equals(long.class)) {
field.set(model, in.readLong());
} else if (field.getType().equals(String.class)) {
field.set(model, in.readString());
} else if (field.getType().equals(boolean.class)) {
field.set(model, in.readByte() == 1);
} else if (field.getType().equals(Date.class)) {
Date date = new Date(in.readLong());
field.set(model, date);
} else if (GlobalParcelable.class.isAssignableFrom(field.getType())) {
Log.e("GlobalParcelable", "read GlobalParcelable: " + " (" + field.getType().toString() + ")");
field.set(model, in.readParcelable(field.getType().getClassLoader()));
} else {
// wtf
Log.e("GlobalParcelable", "Could not read field from parcel: " + field.getName() + " (" + field.getType().toString() + ")");
}
}
}
/*
* Comparator object for Members, Fields, and Methods
*/
private static Comparator<Field> compareMemberByName =
new CompareMemberByName();
private static class CompareMemberByName implements Comparator {
public int compare(Object o1, Object o2) {
String s1 = ((Member) o1).getName();
String s2 = ((Member) o2).getName();
if (o1 instanceof Method) {
s1 += getSignature((Method) o1);
s2 += getSignature((Method) o2);
} else if (o1 instanceof Constructor) {
s1 += getSignature((Constructor) o1);
s2 += getSignature((Constructor) o2);
}
return s1.compareTo(s2);
}
}
/**
* Compute the JVM signature for the class.
*/
private static String getSignature(Class clazz) {
String type = null;
if (clazz.isArray()) {
Class cl = clazz;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < dimensions; i++) {
sb.append("[");
}
sb.append(getSignature(cl));
type = sb.toString();
} else if (clazz.isPrimitive()) {
if (clazz == Integer.TYPE) {
type = "I";
} else if (clazz == Byte.TYPE) {
type = "B";
} else if (clazz == Long.TYPE) {
type = "J";
} else if (clazz == Float.TYPE) {
type = "F";
} else if (clazz == Double.TYPE) {
type = "D";
} else if (clazz == Short.TYPE) {
type = "S";
} else if (clazz == Character.TYPE) {
type = "C";
} else if (clazz == Boolean.TYPE) {
type = "Z";
} else if (clazz == Void.TYPE) {
type = "V";
}
} else {
type = "L" + clazz.getName().replace('.', '/') + ";";
}
return type;
}
/*
* Compute the JVM method descriptor for the method.
*/
private static String getSignature(Method meth) {
StringBuffer sb = new StringBuffer();
sb.append("(");
Class[] params = meth.getParameterTypes(); // avoid clone
for (int j = 0; j < params.length; j++) {
sb.append(getSignature(params[j]));
}
sb.append(")");
sb.append(getSignature(meth.getReturnType()));
return sb.toString();
}
/*
* Compute the JVM constructor descriptor for the constructor.
*/
private static String getSignature(Constructor cons) {
StringBuffer sb = new StringBuffer();
sb.append("(");
Class[] params = cons.getParameterTypes(); // avoid clone
for (int j = 0; j < params.length; j++) {
sb.append(getSignature(params[j]));
}
sb.append(")V");
return sb.toString();
}
}
package com.yunkapay.push.mobile.notification;
import android.os.Parcel;
import android.os.Parcelable;
import com.yunkapay.push.mobile.parcelable.GlobalParcelable;
import com.yunkapay.push.mobile.util.Logger;
import org.json.JSONObject;
/**
* Created with IntelliJ IDEA.
* User: zac
* Date: 12/2/13
* Time: 2:26 PM
* To change this template use File | Settings | File Templates.
*/
public class XJNotification extends GlobalParcelable {
public static final String ELEMENT_NAME = "notification";
public static final String NAMESPACE = "pubsub:message:notification";
public static final String NOTIFICATION_NODE = "node";
public static final String NOTIFICATION_ID = "id";
public static final String NOTIFICATION_TITLE = "title";
public static final String NOTIFICATION_CONTENT = "content";
public static final String NOTIFICATION_TYPE = "type";
public static final String NOTIFICATION_IMAGE_URL = "image_url";
public static final String NOTIFICATION_LINK = "link";
public static final String NOTIFICATION_TIME = "time";
public static final String NOTIFICATION_TIME_TO_LIVE = "time_to_live";
public String mNotificationID;
public String mNode;
public String mTitle;
public String mContent;
public long mTime;
public int mTimeToLive;
public XJNotification(JSONObject jsonObject) {
}
public XJNotification() {
super();
}
public static final Parcelable.Creator<XJNotification> CREATOR = new Parcelable.Creator<XJNotification>() {
public XJNotification createFromParcel(Parcel in) {
// get class from first parcelled item
Class<?> parceledClass;
try {
parceledClass = Class.forName(in.readString());
Logger.i("Creator: " + parceledClass.getSimpleName());
// create instance of that class
XJNotification model = (XJNotification) parceledClass.newInstance();
rehydrate(model, in);
return model;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public XJNotification[] newArray(int size) {
return new XJNotification[size];
}
};
public String getNotificationID() {
return this.mNotificationID;
}
public String getNode() {
return this.mNode;
}
public String getTitle() {
return this.mTitle;
}
public String getContent() {
return this.mContent;
}
public static String getElementName() {
return ELEMENT_NAME;
}
public long getTime() {
return this.mTime;
}
public int getTimeToLive() {
return this.mTimeToLive;
}
public void setNotificationID(String notificationID) {
this.mNotificationID = notificationID;
}
public void setNode(String node) {
this.mNode = node;
}
public void setTitle(String title) {
this.mTitle = title;
}
public void setContent(String content) {
this.mContent = content;
}
public void setTime(long time) {
this.mTime = time;
}
public void setTimeToLive(int timeToLive) {
this.mTimeToLive = timeToLive;
}
public NotificationType getType() {
return NotificationType.UNKNOWN;
}
}