package com.peterhi.runtime;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import com.peterhi.net.Protocol;
import com.peterhi.schemata.common.LanguageString;
import com.peterhi.schemata.common.LanguageStringItem;
public class RT {
public static final int VAR_INT_SHIFT = 2;
public static final int INT6_SERIAL_ID = 0;
public static final int INT14_SERIAL_ID = 1;
public static final int INT30_SERIAL_ID = 2;
public static final int INT62_SERIAL_ID = 3;
public static final int INT6_FULL_LENGTH = 8;
public static final int INT14_FULL_LENGTH = 16;
public static final int INT30_FULL_LENGTH = 32;
public static final int INT62_FULL_LENGTH = 64;
public static final int INT6_DATA_LENGTH = INT6_FULL_LENGTH - 2;
public static final int INT14_DATA_LENGTH = INT14_FULL_LENGTH - 2;
public static final int INT30_DATA_LENGTH = INT30_FULL_LENGTH - 2;
public static final int INT62_DATA_LENGTH = INT62_FULL_LENGTH - 2;
public static final long INT6_MAX_SIGNED = (long )(Math.pow(2, INT6_DATA_LENGTH - 1) - 1);
public static final long INT14_MAX_SIGNED = (long )(Math.pow(2, INT14_DATA_LENGTH - 1) - 1);
public static final long INT30_MAX_SIGNED = (long )(Math.pow(2, INT30_DATA_LENGTH - 1) - 1);
public static final long INT62_MAX_SIGNED = (long )(Math.pow(2, INT62_DATA_LENGTH - 1) - 1);
public static final long INT6_MASK = INT6_MAX_SIGNED;
public static final long INT14_MASK = INT14_MAX_SIGNED;
public static final long INT30_MASK = INT30_MAX_SIGNED;
public static final long INT62_MASK = INT62_MAX_SIGNED;
public static final long INT6_MAX_UNSIGNED = (long )(Math.pow(2, INT6_DATA_LENGTH - 0) - 1);
public static final long INT14_MAX_UNSIGNED = (long )(Math.pow(2, INT14_DATA_LENGTH - 0) - 1);
public static final long INT30_MAX_UNSIGNED = (long )(Math.pow(2, INT30_DATA_LENGTH - 0) - 1);
public static final long INT62_MAX_UNSIGNED = (long )(Math.pow(2, INT62_DATA_LENGTH - 0) - 1);
public static final long INT6_MIN = (long )(-Math.pow(2, INT6_DATA_LENGTH - 1));
public static final long INT14_MIN = (long)(-Math.pow(2, INT14_DATA_LENGTH - 1));
public static final long INT30_MIN = (long )(-Math.pow(2, INT30_DATA_LENGTH - 1));
public static final long INT62_MIN = (long )(-Math.pow(2, INT62_DATA_LENGTH - 1));
public static final int RT_NULL = 0;
public static final int RT_SINGLE = 64;
public static final int RT_MULTI = 128;
public static final int RST_BOOLEAN = 1;
public static final int RST_BYTE = 2;
public static final int RST_CHARACTER = 3;
public static final int RST_SHORT = 4;
public static final int RST_INTEGER = 5;
public static final int RST_LONG = 6;
public static final int RST_FLOAT = 7;
public static final int RST_DOUBLE = 8;
public static final int RST_STRING = 9;
public static final int RST_PROTOCOL = 10;
public static final int RST_BOOLEANS = 11;
public static final int RST_BYTES = 12;
public static final int RST_CHARS = 13;
public static final int RST_SHORTS = 14;
public static final int RST_INTS = 15;
public static final int RST_LONGS = 16;
public static final int RST_FLOATS = 17;
public static final int RST_DOUBLES = 18;
public static Field[] fields(Class<?> type, String name) {
if (type == null) {
throw new NullPointerException();
}
if (name == null) {
throw new NullPointerException();
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
List<Field> allFieldList = new ArrayList<Field>();
Field[] fieldArray = type.getFields();
Field[] declaredFieldArray = type.getDeclaredFields();
for (Field field : fieldArray) {
String fieldName = field.getName();
boolean same = fieldName.equals(name);
if (!same) {
continue;
}
allFieldList.add(field);
}
for (Field declaredField : declaredFieldArray) {
String declaredFieldName = declaredField.getName();
boolean same = declaredFieldName.equals(name);
if (!same) {
continue;
}
allFieldList.add(declaredField);
}
Field[] allFieldArray = new Field[allFieldList.size()];
allFieldArray = allFieldList.toArray(allFieldArray);
Arrays.sort(allFieldArray, new Comparator<Field>() {
@Override
public int compare(Field field, Field otherField) {
if (field == null && otherField == null) {
return 0;
}
if (field == null) {
return -1;
}
if (otherField == null) {
return 1;
}
String fieldName = field.getName();
String otherFieldName = otherField.getName();
return fieldName.compareTo(otherFieldName);
}
});
return allFieldArray;
}
public static Method[] methods(Class<?> type, String name) {
if (type == null) {
throw new NullPointerException();
}
if (name == null) {
throw new NullPointerException();
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
List<Method> allMethodList = new ArrayList<Method>();
Method[] methodArray = type.getMethods();
Method[] declaredMethodArray = type.getDeclaredMethods();
for (Method method : methodArray) {
String methodName = method.getName();
boolean same = methodName.equals(name);
if (!same) {
continue;
}
allMethodList.add(method);
}
for (Method declaredMethod : declaredMethodArray) {
String declaredMethodName = declaredMethod.getName();
boolean same = declaredMethodName.equals(name);
if (!same) {
continue;
}
allMethodList.add(declaredMethod);
}
Method[] allMethodArray = new Method[allMethodList.size()];
allMethodArray = allMethodList.toArray(allMethodArray);
Arrays.sort(allMethodArray, new Comparator<Method>() {
@Override
public int compare(Method method, Method otherMethod) {
if (method == null && otherMethod == null) {
return 0;
}
if (method == null) {
return -1;
}
if (otherMethod == null) {
return 1;
}
String methodName = method.getName();
String otherMethodName = otherMethod.getName();
return methodName.compareTo(otherMethodName);
}
});
return allMethodArray;
}
public static Object call(String name, Class<?> type, Object...paramTypesAndArgs)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return call(type, false, name, paramTypesAndArgs);
}
public static Object call(Object target, String name, Object...paramTypesAndArgs)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
return call(target, true, name, paramTypesAndArgs);
}
public static Object call(Object target, boolean instance, String name, Object...paramTypesAndArgs)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
if (target == null) {
throw new NullPointerException();
}
if (name == null) {
throw new NullPointerException();
}
if (paramTypesAndArgs == null) {
throw new NullPointerException();
}
Class<?> type;
if (instance) {
type = target.getClass();
} else {
if (target instanceof Class<?>) {
type = (Class<?> )target;
} else {
throw new ClassCastException();
}
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
int quotient = paramTypesAndArgs.length / 2;
int remainder = paramTypesAndArgs.length % 2;
if (remainder != 0) {
throw new IllegalArgumentException();
}
List<Class<?>> paramTypeList = new ArrayList<Class<?>>();
List<Object> paramArgList = new ArrayList<Object>();
for (int i = 0; i < quotient; i++) {
Class<?> paramType = (Class<?> )paramTypesAndArgs[i * 2 + 0];
Object paramArg = paramTypesAndArgs[i * 2 + 1];
if (paramType == null) {
throw new IllegalArgumentException();
}
paramTypeList.add(paramType);
paramArgList.add(paramArg);
}
Class<?>[] paramTypeArray = new Class<?>[paramTypeList.size()];
Object[] paramArgArray = new Object[paramArgList.size()];
paramTypeArray = paramTypeList.toArray(paramTypeArray);
paramArgArray = paramArgList.toArray(paramArgArray);
Method[] methods = methods(type, name);
Method method = null;
for (int i = 0; i < methods.length; i++) {
int modifiers = methods[i].getModifiers();
boolean classifier = Modifier.isStatic(modifiers);
boolean valid = instance != classifier;
if (!valid) {
continue;
}
Class<?>[] methodParamTypeArray = methods[i].getParameterTypes();
boolean signature = Arrays.equals(methodParamTypeArray, paramTypeArray);
if (!signature) {
continue;
}
method = methods[i];
break;
}
if (method == null) {
throw new NoSuchMethodException();
}
Object param;
if (instance) {
param = target;
} else {
param = null;
}
Object value = method.invoke(param, paramArgArray);
return value;
}
public static Object get(Object target, String name)
throws IllegalAccessException, InvocationTargetException {
return get(target, true, name);
}
public static Object get(String name, Class<?> type)
throws IllegalAccessException, InvocationTargetException {
return get(type, false, name);
}
public static Object get(Object target, boolean instance, String name)
throws IllegalAccessException, InvocationTargetException {
if (target == null) {
throw new NullPointerException();
}
if (name == null) {
throw new NullPointerException();
}
Class<?> type;
if (instance) {
type = target.getClass();
} else {
if (target instanceof Class<?>) {
type = (Class<?> )target;
} else {
throw new ClassCastException();
}
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
Method method = null;
{
StringBuilder builder = new StringBuilder();
builder.append("is");
builder.append(Character.toUpperCase(name.charAt(0)));
builder.append(name, 1, name.length());
Method[] methods = methods(type, builder.toString());
for (int i = 0; i < methods.length; i++) {
int modifiers = methods[i].getModifiers();
boolean classifier = Modifier.isStatic(modifiers);
boolean valid = instance != classifier;
if (!valid) {
continue;
}
Class<?>[] methodParamTypeArray = methods[i].getParameterTypes();
Class<?> methodReturnType = methods[i].getReturnType();
if (methodParamTypeArray.length != 0) {
continue;
}
if (methodReturnType == void.class) {
continue;
}
if (methodReturnType == Void.class) {
continue;
}
method = methods[i];
break;
}
}
if (method == null) {
StringBuilder builder = new StringBuilder();
builder.append("get");
builder.append(Character.toUpperCase(name.charAt(0)));
builder.append(name, 1, name.length());
Method[] methods = methods(type, builder.toString());
for (int i = 0; i < methods.length; i++) {
int modifiers = methods[i].getModifiers();
boolean classifier = Modifier.isStatic(modifiers);
boolean valid = instance != classifier;
if (!valid) {
continue;
}
Class<?>[] methodParamTypeArray = methods[i].getParameterTypes();
Class<?> methodReturnType = methods[i].getReturnType();
if (methodParamTypeArray.length != 0) {
continue;
}
if (methodReturnType == void.class) {
continue;
}
if (methodReturnType == Void.class) {
continue;
}
method = methods[i];
break;
}
}
if (method == null) {
Method[] methods = methods(type, name);
for (int i = 0; i < methods.length; i++) {
int modifiers = methods[i].getModifiers();
boolean classifier = Modifier.isStatic(modifiers);
boolean valid = instance != classifier;
if (!valid) {
continue;
}
Class<?>[] methodParamTypeArray = methods[i].getParameterTypes();
Class<?> methodReturnType = methods[i].getReturnType();
if (methodParamTypeArray.length != 0) {
continue;
}
if (methodReturnType == void.class) {
continue;
}
if (methodReturnType == Void.class) {
continue;
}
method = methods[i];
break;
}
}
Object param;
if (instance) {
param = target;
} else {
param = null;
}
Object value = null;
boolean direct = (method == null);
if (!direct) {
try {
value = method.invoke(param);
} catch (IllegalAccessException ex) {
direct = true;
}
}
if (direct) {
Field[] fields = fields(type, name);
boolean accessed = false;
for (Field field : fields) {
try {
value = field.get(param);
accessed = true;
break;
} catch (IllegalAccessException innerEx) {
continue;
}
}
if (!accessed) {
throw new IllegalAccessException();
}
}
return value;
}
public static void set(Object target, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
set(target, true, name, value);
}
public static void set(String name, Class<?> type, Object value)
throws IllegalAccessException, InvocationTargetException {
set(type, false, name, value);
}
public static void set(Object target, boolean instance, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
if (target == null) {
throw new NullPointerException();
}
if (name == null) {
throw new NullPointerException();
}
Class<?> type;
if (instance) {
type = target.getClass();
} else {
if (target instanceof Class<?>) {
type = (Class<?> )target;
} else {
throw new ClassCastException();
}
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
Method method = null;
{
StringBuilder builder = new StringBuilder();
builder.append("set");
builder.append(Character.toUpperCase(name.charAt(0)));
builder.append(name, 1, name.length());
Method[] methods = methods(type, builder.toString());
for (int i = 0; i < methods.length; i++) {
int modifiers = methods[i].getModifiers();
boolean classifier = Modifier.isStatic(modifiers);
boolean valid = instance != classifier;
if (!valid) {
continue;
}
Class<?>[] methodParamTypeArray = methods[i].getParameterTypes();
Class<?> methodReturnType = methods[i].getReturnType();
if (methodParamTypeArray.length != 1) {
continue;
}
if (methodReturnType != void.class) {
if (methodReturnType != Void.class) {
continue;
}
}
method = methods[i];
break;
}
}
if (method == null) {
Method[] methods = methods(type, name);
for (int i = 0; i < methods.length; i++) {
int modifiers = methods[i].getModifiers();
boolean classifier = Modifier.isStatic(modifiers);
boolean valid = instance != classifier;
if (!valid) {
continue;
}
Class<?>[] methodParamTypeArray = methods[i].getParameterTypes();
Class<?> methodReturnType = methods[i].getReturnType();
if (methodParamTypeArray.length != 0) {
continue;
}
if (methodReturnType != void.class) {
if (methodReturnType != Void.class) {
continue;
}
}
method = methods[i];
break;
}
}
Object param;
if (instance) {
param = target;
} else {
param = null;
}
boolean direct = (method == null);
if (!direct) {
try {
method.invoke(param, value);
} catch (IllegalAccessException ex) {
direct = true;
}
}
if (direct) {
Field[] fields = fields(type, name);
boolean modified = false;
for (Field field : fields) {
try {
field.set(param, value);
modified = true;
break;
} catch (IllegalAccessException innerEx) {
continue;
}
}
if (!modified) {
throw new IllegalAccessException();
}
}
}
public static Object defaultInvoke(Class<?> type, Object proxy, Method method, Object[] args) throws Exception {
if (method.getDeclaringClass() == Object.class) {
if (method.getReturnType() == int.class &&
method.getName().equals("hashCode") &&
method.getParameterTypes().length == 0) {
return System.identityHashCode(proxy);
} else if (method.getReturnType() == boolean.class &&
method.getName().equals("equals") &&
method.getParameterTypes().length == 1 &&
method.getParameterTypes()[0] == Object.class) {
int hashCode = proxy.hashCode();
int otherHashCode = args[0] == null ? 0 : args[0].hashCode();
return hashCode == otherHashCode;
} else if (method.getReturnType() == String.class &&
method.getName().equals("toString") &&
method.getParameterTypes().length == 0) {
int hashCode = proxy.hashCode();
String hexHashCode = Integer.toHexString(hashCode);
return MessageFormat.format(Constants.PATTERN_TO_STRING, type.getName(), hexHashCode);
}
}
throw new UnsupportedOperationException();
}
public static URL getClassResource(Class<?> type, String suffix) {
if (type == null) {
throw new NullPointerException();
}
if (suffix == null) {
suffix = "";
}
StringBuilder builder = new StringBuilder();
builder.append('/');
String name = type.getName();
name = name.replaceAll("\\.", "/");
builder.append(name);
if (!suffix.startsWith(".")) {
builder.append(".");
}
builder.append(suffix);
String path = builder.toString();
return type.getResource(path);
}
public static void checkForNull(Object object) throws NullPointerException {
if (object == null) {
throw new NullPointerException("Object is null.");
}
}
public static void checkForEmpty(Object array) throws NullPointerException, IllegalArgumentException {
checkForNull(array);
int length = Array.getLength(array);
if (length <= 0) {
throw new IllegalArgumentException("Array length is zero or less.");
}
}
public static void checkForInvalid(int index, int length) throws IllegalArgumentException {
if (index < 0) {
throw new IllegalArgumentException("Index is negative.");
}
if (length <= 0) {
throw new IllegalArgumentException("Length is zero or less.");
}
}
public static void checkBuffer(byte[] buffer, int offset, int length) throws NullPointerException, IllegalArgumentException {
checkForEmpty(buffer);
checkForInvalid(offset, length);
if (offset + length > buffer.length) {
throw new IllegalArgumentException("Index + length is greater than array length.");
}
}
public static boolean equals(Object object, Object other) {
if (object == other) {
return true;
}
if (object != null) {
return object.equals(other);
} else {
return other.equals(object);
}
}
public static URL getSystemFile(String name) throws IOException {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException();
}
File dir = new File(System.getProperty("user.dir"));
if (!dir.exists()) {
try {
dir = new File(RT.class.getProtectionDomain().getCodeSource().getLocation().toURI());
} catch (URISyntaxException ex) {
throw new IOException(ex);
}
}
File file = new File(dir, name);
if (!file.exists()) {
throw new FileNotFoundException();
}
return file.toURI().toURL();
}
public static String getLanguageString(LanguageString languageString, Locale locale) {
if (languageString == null) {
throw new NullPointerException();
}
if (locale == null) {
locale = Locale.getDefault();
}
LanguageStringItem[] languageStringItems = languageString.getLanguageStringItemArray();
if (languageStringItems == null || languageStringItems.length == 0) {
throw new IllegalArgumentException();
}
for (LanguageStringItem languageStringItem : languageStringItems) {
String language = languageStringItem.getLanguage();
String[] components = language.split("_");
if (locale.equals(new Locale(components[0], components[1]))) {
return languageStringItem.newCursor().getTextValue();
}
}
return languageStringItems[0].newCursor().getTextValue();
}
public static String getLanguageString(LanguageString languageString) {
return getLanguageString(languageString, Locale.getDefault());
}
public static <T extends StringResource> T getStringResource(Class<T> type) {
if (type == null) {
throw new NullPointerException();
}
InvocationHandler invocationHandler = new StringResourceInvocationHandler(type);
Class<?>[] interfaces = new Class<?>[] { type };
ClassLoader loader = type.getClassLoader();
Object object = Proxy.newProxyInstance(loader, interfaces, invocationHandler);
return type.cast(object);
}
public static Comparator<Class<?>> getClassNameComparator() {
return ClassNameComparator.getInstance();
}
public static Comparator<Method> getMethodNameComparator() {
return MethodNameComparator.getInstance();
}
public static boolean isFlagged(int[] pointer, int flags, boolean exact) {
if (pointer == null) {
throw new NullPointerException();
}
if (pointer.length != 1) {
throw new IllegalArgumentException();
}
if (flags == 0) {
throw new IllegalArgumentException();
}
if (exact) {
return pointer[0] == flags;
}
return (pointer[0] & flags) == flags;
}
public static boolean isFlagged(int value, int flags, boolean exact) {
int[] pointer = new int[] { value };
return isFlagged(pointer, flags, exact);
}
public static boolean isFlagged(int[] pointer, int flags) {
return isFlagged(pointer, flags, false);
}
public static boolean isFlagged(int value, int flags) {
return isFlagged(value, flags, false);
}
public static boolean addFlags(int[] pointer, int flags) {
if (isFlagged(pointer, flags)) {
return false;
}
pointer[0] |= flags;
return true;
}
public static boolean removeFlags(int[] pointer, int flags) {
if (!isFlagged(pointer, flags)) {
return false;
}
pointer[0] &= ~flags;
return true;
}
public static boolean flipFlags(int[] pointer, int flags) {
if (pointer == null) {
throw new NullPointerException();
}
if (pointer.length != 1) {
throw new IllegalArgumentException();
}
int absentFlagsToAdd = (pointer[0] ^ flags);
int presentFlagsToRemove = (pointer[0] & flags);
if (absentFlagsToAdd == 0 && presentFlagsToRemove == 0) {
return false;
}
if (absentFlagsToAdd != 0) {
addFlags(pointer, absentFlagsToAdd);
}
if (presentFlagsToRemove != 0) {
removeFlags(pointer, presentFlagsToRemove);
}
return true;
}
public static <T> T newLocalProtocol(Class<T> protocolType) throws InstantiationException {
if (protocolType == null) {
throw new NullPointerException();
}
if (!Protocol.class.isAssignableFrom(protocolType)) {
throw new IllegalArgumentException();
}
Abstract annotation = protocolType.getAnnotation(Abstract.class);
if (annotation != null) {
throw new InstantiationException(MessageFormat.format("{0} is annotated as \"abstract\"", protocolType));
}
InvocationHandler invocationHandler = new ProtocolInvocationHandler(protocolType);
Object protocol = Proxy.newProxyInstance(protocolType.getClassLoader(), new Class<?>[] { protocolType }, invocationHandler);
return protocolType.cast(protocol);
}
public static byte[] serializeProtocol(Protocol protocol) throws IOException {
if (protocol == null) {
throw new NullPointerException();
}
ProtocolInvocationHandler pih = (ProtocolInvocationHandler )Proxy.getInvocationHandler(protocol);
final Class<?> protocolType = pih.getProtocolType();
String protocolTypeName = protocolType.getName();
final String protocolTypeSimpleName = protocolType.getSimpleName();
final String protocolTypePrefix = protocolTypeName.substring(0, protocolTypeName.length() - protocolTypeSimpleName.length());
// Comparator<Class<?>> keyComparator = new Comparator<Class<?>>() {
// @Override
// public int compare(Class<?> class0, Class<?> class1) {
// String className0 = class0.getName();
// String className1 = class1.getName();
// return className0.compareTo(className1);
// }
// };
Comparator<Class<?>> classComparator = new Comparator<Class<?>>() {
@Override
public int compare(Class<?> class0, Class<?> class1) {
if (class0 == class1) {
return 0;
}
if (class0 == protocolType) {
return -1;
}
if (class1 == protocolType) {
return 1;
}
String name0 = class0.getName();
String simple0 = class0.getSimpleName();
String prefix0 = name0.substring(0, name0.length() - simple0.length());
String name1 = class1.getName();
String simple1 = class1.getSimpleName();
String prefix1 = name1.substring(0, name1.length() - simple1.length());
if (prefix0.equals(prefix1)) {
if (simple0.equals(protocolTypeSimpleName)) {
return -1;
} else if (simple1.equals(protocolTypeSimpleName)) {
return 1;
} else {
return name0.compareTo(name1);
}
} else {
if (prefix0.equals(protocolTypePrefix)) {
return -1;
} else if (prefix1.equals(protocolTypePrefix)) {
return 1;
} else {
return name0.compareTo(name1);
}
}
}
};
// SortedMap<Class<?>, SortedSet<Protocol>> protocolObjectMap = new TreeMap<Class<?>, SortedSet<Protocol>>(keyComparator);
// fillProtocolObjectMap(protocol, protocolObjectMap);
SortedMap<Class<?>, SortedSet<Protocol>> protocolObjectMap2 = new TreeMap<Class<?>, SortedSet<Protocol>>(classComparator);
fillProtocolObjectMap(protocol, protocolObjectMap2);
StringBuilder expr = new StringBuilder();
String lastExpr = null;
for (Class<?> type : protocolObjectMap2.keySet()) {
String name = type.getName();
String simpleName = type.getSimpleName();
String prefix = name.substring(0, name.length() - simpleName.length());
if (prefix.equals(lastExpr)) {
expr.append(',');
expr.append(simpleName);
} else {
if (lastExpr != null) {
expr.append(';');
}
expr.append(name);
lastExpr = prefix;
}
}
System.out.println(expr);
// SortedMap<String, SortedSet<String>> typeNameMap = new TreeMap<String, SortedSet<String>>();
//
// for (Class<?> type : protocolObjectMap.keySet()) {
// String typeName = type.getName();
// String simpleTypeName = type.getSimpleName();
// String commonTypeNamePrefix = typeName.substring(0, typeName.length() - simpleTypeName.length());
// SortedSet<String> simpleTypeNameSet = getSimpleTypeNameSet(typeNameMap, commonTypeNamePrefix);
// simpleTypeNameSet.add(simpleTypeName);
// }
MemoryStream ms = new MemoryStream();
// StringBuilder typeNameExpr = new StringBuilder();
// boolean key1st = true;
// List<Class<?>> typeList = new ArrayList<Class<?>>();
//
// for (String commonTypeNamePrefix : typeNameMap.keySet()) {
// if (key1st) {
// key1st = false;
// } else {
// typeNameExpr.append(';');
// }
//
// SortedSet<String> simpleTypeNameSet = typeNameMap.get(commonTypeNamePrefix);
// boolean val1st = true;
//
// for (String simpleTypeName : simpleTypeNameSet) {
// if (val1st) {
// val1st = false;
// typeNameExpr.append(commonTypeNamePrefix);
// typeNameExpr.append(simpleTypeName);
// } else {
// typeNameExpr.append(',');
// typeNameExpr.append(simpleTypeName);
// }
//
// try {
// typeList.add(Class.forName(commonTypeNamePrefix + simpleTypeName));
// } catch (ClassNotFoundException ex) {
// throw new RuntimeException(ex);
// }
// }
// }
//
// ms.writeLength(new Length(typeNameExpr.length()));
// ms.writeBytes(typeNameExpr.toString());
ms.writeLength(new Length(expr.length()));
ms.writeBytes(expr.toString());
for (Class<?> type : protocolObjectMap2.keySet()) {
ms.writeLength(new Length(protocolObjectMap2.get(type).size()));
}
// for (Class<?> type : typeList) {
// ms.writeLength(new Length(protocolObjectMap.get(type).size()));
// }
List<Protocol> protocolsInOrder = new ArrayList<Protocol>();
Set<Protocol> serializedProtocols = new HashSet<Protocol>();
// for (Class<?> type : typeList) {
// SortedSet<Protocol> protocolObjectSet = protocolObjectMap.get(type);
//
// for (Protocol protocolObject : protocolObjectSet) {
// protocolsInOrder.add(protocolObject);
// }
// }
// protocolsInOrder.remove(protocol);
// protocolsInOrder.add(0, protocol);
for (Class<?> type : protocolObjectMap2.keySet()) {
SortedSet<Protocol> values = protocolObjectMap2.get(type);
for (Protocol value : values) {
protocolsInOrder.add(value);
}
}
for (Class<?> type : protocolObjectMap2.keySet()) {
SortedSet<Protocol> values = protocolObjectMap2.get(type);
for (Protocol value : values) {
writeObject(ms, type, value, protocolsInOrder, serializedProtocols, false);
}
}
protocolsInOrder.remove(protocol);
protocolsInOrder.add(0, protocol);
for (Protocol protocolInOrder : protocolsInOrder) {
ProtocolInvocationHandler h = (ProtocolInvocationHandler )Proxy.getInvocationHandler(protocolInOrder);
writeObject(ms, h.getProtocolType(), protocolInOrder, protocolsInOrder, serializedProtocols, false);
}
// ms.writeLength(new Length(protocolsInOrder.indexOf(protocol)));
byte[] bytes = new byte[ms.available()];
ms.readFully(bytes);
return bytes;
}
private static void writeObject(MemoryStream ms, Class<?> type, Object object, List<Protocol> protocolsInOrder, Set<Protocol> serializedProtocols, boolean writeRefOnly) throws IOException {
if (Protocol.class.isAssignableFrom(type)) {
if (writeRefOnly) {
int index = protocolsInOrder.indexOf(object);
if (object == null || index < 0) {
ms.writeLength(new Length(0));
} else {
ms.writeLength(new Length(index + 1));
}
} else {
Protocol protocol = (Protocol )object;
serializedProtocols.add(protocol);
ProtocolInvocationHandler pih = (ProtocolInvocationHandler )Proxy.getInvocationHandler(object);
Map<String, Object> propertyMap = pih.getPropertyMap();
for (String key : propertyMap.keySet()) {
Method[] methods = type.getMethods();
String get = "get" + Character.toUpperCase(key.charAt(0)) + key.substring(1);
String is = "is" + Character.toUpperCase(key.charAt(0)) + key.substring(1);
String coll = key;
Method theMethod = null;
for (Method method : methods) {
if (method.getName().equals(get) || method.getName().equals(is)) {
theMethod = method;
} else if (method.getName().equals(coll) && (method.getReturnType() == ProtocolSet.class ||
method.getReturnType() == ProtocolList.class || method.getReturnType() == ProtocolMap.class)) {
theMethod = method;
}
}
if (theMethod == null) {
throw new IOException("Object is corrupted: unknown method for property '" + key + "'");
}
Class<?> theType = theMethod.getReturnType();
try {
Object theValue = theMethod.invoke(protocol);
writeObject(ms, theType, theValue, protocolsInOrder, serializedProtocols, true);
} catch (Exception ex) {
throw new IOException(ex);
}
}
}
} else if (type == boolean.class) {
ms.writeBoolean(object == null ? false : (Boolean )object);
} else if (type == byte.class) {
ms.writeByte(object == null ? (byte )0 : (Byte )object);
} else if (type == char.class) {
ms.writeChar(object == null ? '\0' : (Character )object);
} else if (type == short.class) {
ms.writeShort(object == null ? (short )0 : (Short )object);
} else if (type == int.class) {
ms.writeInt(object == null ? 0 : (Integer )object);
} else if (type == long.class) {
ms.writeLong(object == null ? 0L : (Long )object);
} else if (type == float.class) {
ms.writeFloat(object == null ? 0.0f : (Float )object);
} else if (type == double.class) {
ms.writeDouble(object == null ? 0.0 : (Double )object);
} else if (type == Boolean.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeBoolean((Boolean )object);
}
} else if (type == Byte.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeByte((Byte )object);
}
} else if (type == Character.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeChar((Character )object);
}
} else if (type == Short.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeShort((Short )object);
}
} else if (type == Integer.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeInt((Integer )object);
}
} else if (type == Long.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeLong((Long )object);
}
} else if (type == Float.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeFloat((Float )object);
}
} else if (type == Double.class) {
ms.writeBoolean(object != null);
if (object != null) {
ms.writeDouble((Double )object);
}
} else if (type == boolean[].class) {
if (object == null) {
ms.writeLength(new Length(0));
} else {
boolean[] array = (boolean[] )object;
ms.writeLength(new Length(array.length + 1));
ms.writeBooleans(array);
}
} else if (type == byte[].class) {
if (object == null) {
ms.writeLength(new Length(0));
} else {
byte[] array = (byte[] )object;
ms.writeLength(new Length(array.length + 1));
ms.write(array);
}
} else if (type.isArray()) {
if (object == null) {
ms.writeLength(new Length(0));
} else {
int length = Array.getLength(object);
ms.writeLength(new Length(length + 1));
for (int i = 0; i < length; i++) {
writeObject(ms, type.getComponentType(), Array.get(object, i), protocolsInOrder, serializedProtocols, true);
}
}
} else if (type == String.class) {
if (object == null) {
ms.writeLength(new Length(0));
} else {
String string = (String )object;
ms.writeLength(new Length(string.length() + 1));
ms.writeUTFBase(string, string.length());
}
} else if (type == ProtocolSet.class || type == ProtocolList.class) {
ProtocolSet set = (ProtocolSet )object;
ms.writeLength(new Length(set.size()));
Object[] array = set.toArray();
for (Object item : array) {
writeObject(ms, Object.class, item, protocolsInOrder, serializedProtocols, true);
}
} else if (type == ProtocolMap.class) {
ProtocolMap map = (ProtocolMap )object;
ms.writeLength(new Length(map.size()));
Object[] keys = map.keys();
for (Object key : keys) {
writeObject(ms, Object.class, key, protocolsInOrder, serializedProtocols, true);
writeObject(ms, Object.class, map.get(key), protocolsInOrder, serializedProtocols, true);
}
}
else if (type == Object.class) {
int rttype = determineRuntimeType(object);
int rt = rttype & (RT_SINGLE | RT_MULTI);
int rst = rttype & 0x3f;
ms.write(rttype);
if (rt == RT_SINGLE) {
if (rst == RST_BOOLEAN) {
ms.writeBoolean((Boolean )object);
} else if (rst == RST_BYTE) {
ms.writeByte((Byte )object);
} else if (rst == RST_CHARACTER) {
ms.writeChar((Character )object);
} else if (rst == RST_SHORT) {
ms.writeShort((Short )object);
} else if (rst == RST_INTEGER) {
ms.writeInt((Integer )object);
} else if (rst == RST_LONG) {
ms.writeLong((Long )object);
} else if (rst == RST_FLOAT) {
ms.writeFloat((Float )object);
} else if (rst == RST_DOUBLE) {
ms.writeDouble((Double )object);
} else if (rst == RST_STRING) {
String string = (String )object;
ms.writeLength(new Length(string.length()));
ms.writeUTFBase(string, string.length());
} else if (rst == RST_BOOLEANS) {
boolean[] array = (boolean[] )object;
ms.writeLength(new Length(array.length));
ms.writeBooleans(array);
} else if (rst == RST_BYTES) {
byte[] array = (byte[] )object;
ms.writeLength(new Length(array.length));
ms.write(array);
} else if (rst == RST_CHARS) {
char[] array = (char[] )object;
ms.writeLength(new Length(array.length));
for (char item : array) {
ms.writeChar(item);
}
} else if (rst == RST_SHORTS) {
short[] array = (short[] )object;
ms.writeLength(new Length(array.length));
for (short item : array) {
ms.writeShort(item);
}
} else if (rst == RST_INTS) {
int[] array = (int[] )object;
ms.writeLength(new Length(array.length));
for (int item : array) {
ms.writeInt(item);
}
} else if (rst == RST_LONGS) {
long[] array = (long[] )object;
ms.writeLength(new Length(array.length));
for (long item : array) {
ms.writeLong(item);
}
} else if (rst == RST_FLOATS) {
float[] array = (float[] )object;
ms.writeLength(new Length(array.length));
for (float item : array) {
ms.writeFloat(item);
}
} else if (rst == RST_DOUBLES) {
double[] array = (double[] )object;
ms.writeLength(new Length(array.length));
for (double item : array) {
ms.writeDouble(item);
}
} else if (rst == RST_PROTOCOL) {
int index = protocolsInOrder.indexOf(object);
if (object != null || index >= 0) {
ms.writeLength(new Length(index));
}
} else {
writeObject(ms, object.getClass(), object, protocolsInOrder, serializedProtocols, true);
}
} else if (rt == RT_MULTI) {
type = object.getClass();
int length = Array.getLength(object);
ms.writeLength(new Length(length));
for (int i = 0; i < length; i++) {
Object component = Array.get(object, i);
writeObject(ms, Object.class, component, protocolsInOrder, serializedProtocols, true);
}
}
}
}
private static Object readSingleValue(MemoryStream ms, Class<?> type, List<Protocol> protocolsInOrder) throws IOException {
if (type == boolean.class) {
return ms.readBoolean();
} else if (type == byte.class) {
return ms.readByte();
} else if (type == char.class) {
return ms.readChar();
} else if (type == short.class) {
return ms.readShort();
} else if (type == int.class) {
return ms.readInt();
} else if (type == long.class) {
return ms.readLong();
} else if (type == float.class) {
return ms.readFloat();
} else if (type == double.class) {
return ms.readDouble();
} else if (type == Boolean.class) {
if (ms.readBoolean()) {
return ms.readBoolean();
}
} else if (type == Byte.class) {
if (ms.readBoolean()) {
return ms.readByte();
}
} else if (type == Character.class) {
if (ms.readBoolean()) {
return ms.readChar();
}
} else if (type == Short.class) {
if (ms.readBoolean()) {
return ms.readShort();
}
} else if (type == Integer.class) {
if (ms.readBoolean()) {
return ms.readInt();
}
} else if (type == Long.class) {
if (ms.readBoolean()) {
return ms.readLong();
}
} else if (type == Float.class) {
if (ms.readBoolean()) {
return ms.readFloat();
}
} else if (type == Double.class) {
if (ms.readBoolean()) {
return ms.readDouble();
}
} else if (type == boolean[].class) {
Length length = ms.readLength();
if (length.booleanValue()) {
int intLength = length.intValue() - 1;
boolean[] array = new boolean[intLength];
ms.readBooleans(array);
return array;
}
} else if (type == byte[].class) {
Length length = ms.readLength();
if (length.booleanValue()) {
int intLength = length.intValue() - 1;
byte[] array = new byte[intLength];
ms.readFully(array);
return array;
}
} else if (type.isArray()) {
Length length = ms.readLength();
if (length.booleanValue()) {
int intLength = length.intValue() - 1;
Object array = Array.newInstance(type.getComponentType(), intLength);
for (int i = 0; i < intLength; i++) {
Array.set(array, i, readSingleValue(ms, type.getComponentType(), protocolsInOrder));
}
return array;
}
} else if (type == String.class) {
Length length = ms.readLength();
if (length.booleanValue()) {
int intLength = length.intValue() - 1;
return ms.readUTFBase(intLength);
}
} else if (Protocol.class.isAssignableFrom(type)) {
Length length = ms.readLength();
if (length.booleanValue()) {
int index = length.intValue() - 1;
return protocolsInOrder.get(index);
}
} else if (type == Object.class) {
int rttype = ms.readUnsignedByte();
Class<?> klass = determineRuntimeType(rttype);
if (klass != null) {
if (klass == Boolean.class) {
return ms.readBoolean();
} else if (klass == Byte.class) {
return ms.readByte();
} else if (klass == Character.class) {
return ms.readChar();
} else if (klass == Short.class) {
return ms.readShort();
} else if (klass == Integer.class) {
return ms.readInt();
} else if (klass == Long.class) {
return ms.readLong();
} else if (klass == Float.class) {
return ms.readFloat();
} else if (klass == Double.class) {
return ms.readDouble();
} else if (klass == String.class) {
Length length = ms.readLength();
return ms.readUTFBase(length.intValue());
} else if (klass == boolean[].class) {
Length length = ms.readLength();
boolean[] array = new boolean[length.intValue()];
ms.readBooleans(array);
return array;
} else if (klass == byte[].class) {
Length length = ms.readLength();
byte[] array = new byte[length.intValue()];
ms.readFully(array);
return array;
} else if (klass == char[].class) {
Length length = ms.readLength();
char[] array = new char[length.intValue()];
for (int i = 0; i < array.length; i++) {
array[i] = ms.readChar();
}
return array;
} else if (klass == short[].class) {
Length length = ms.readLength();
short[] array = new short[length.intValue()];
for (int i = 0; i < array.length; i++) {
array[i] = ms.readShort();
}
return array;
} else if (klass == int[].class) {
Length length = ms.readLength();
int[] array = new int[length.intValue()];
for (int i = 0; i < array.length; i++) {
array[i] = ms.readInt();
}
return array;
} else if (klass == long[].class) {
Length length = ms.readLength();
long[] array = new long[length.intValue()];
for (int i = 0; i < array.length; i++) {
array[i] = ms.readLong();
}
return array;
} else if (klass == float[].class) {
Length length = ms.readLength();
float[] array = new float[length.intValue()];
for (int i = 0; i < array.length; i++) {
array[i] = ms.readFloat();
}
return array;
} else if (klass == double[].class) {
Length length = ms.readLength();
double[] array = new double[length.intValue()];
for (int i = 0; i < array.length; i++) {
array[i] = ms.readDouble();
}
return array;
} else if (klass == Protocol.class) {
Length index = ms.readLength();
return protocolsInOrder.get(index.intValue());
}
else if (klass.isArray()) {
Length length = ms.readLength();
Object array = Array.newInstance(klass.getComponentType(), length.intValue());
for (int i = 0; i < length.intValue(); i++) {
Array.set(array, i, readSingleValue(ms, klass.getComponentType(), protocolsInOrder));
}
return array;
}
}
}
return null;
}
private static int determineRuntimeSubtype(Class<?> runtimeClass) {
if (runtimeClass == Boolean.class) {
return RST_BOOLEAN;
} else if (runtimeClass == Byte.class) {
return RST_BYTE;
} else if (runtimeClass == Character.class) {
return RST_CHARACTER;
} else if (runtimeClass == Short.class) {
return RST_SHORT;
} else if (runtimeClass == Integer.class) {
return RST_INTEGER;
} else if (runtimeClass == Long.class) {
return RST_LONG;
} else if (runtimeClass == Float.class) {
return RST_FLOAT;
} else if (runtimeClass == Double.class) {
return RST_DOUBLE;
} else if (runtimeClass == String.class) {
return RST_STRING;
} else if (runtimeClass == boolean[].class) {
return RST_BOOLEANS;
} else if (runtimeClass == byte[].class) {
return RST_BYTES;
} else if (runtimeClass == char[].class) {
return RST_CHARS;
} else if (runtimeClass == short[].class) {
return RST_SHORTS;
} else if (runtimeClass == int[].class) {
return RST_INTS;
} else if (runtimeClass == long[].class) {
return RST_LONGS;
} else if (runtimeClass == float[].class) {
return RST_FLOATS;
} else if (runtimeClass == double[].class) {
return RST_DOUBLES;
} else if (Protocol.class.isAssignableFrom(runtimeClass)) {
return RST_PROTOCOL;
}
return 0;
}
private static int determineRuntimeType(Object object) {
int rttype = 0;
if (object == null) {
rttype |= RT_NULL;
} else {
Class<?> runtimeClass = object.getClass();
if (runtimeClass.isArray() && !runtimeClass.getComponentType().isPrimitive()) {
rttype |= RT_MULTI;
rttype |= determineRuntimeSubtype(runtimeClass.getComponentType());
}
else {
rttype |= RT_SINGLE;
rttype |= determineRuntimeSubtype(runtimeClass);
}
}
return rttype;
}
private static Class<?> determineRuntimeType(int rttype) {
int rt = rttype & (RT_SINGLE | RT_MULTI);
int rst = rttype & 0x3f;
if (rt == RT_NULL) {
return null;
} else {
if (rt == RT_SINGLE) {
if (rst == RST_BOOLEAN) {
return Boolean.class;
} else if (rst == RST_BYTE) {
return Byte.class;
} else if (rst == RST_CHARACTER) {
return Character.class;
} else if (rst == RST_SHORT) {
return Short.class;
} else if (rst == RST_INTEGER) {
return Integer.class;
} else if (rst == RST_LONG) {
return Long.class;
} else if (rst == RST_FLOAT) {
return Float.class;
} else if (rst == RST_DOUBLE) {
return Double.class;
} else if (rst == RST_STRING) {
return String.class;
} else if (rst == RST_BOOLEANS) {
return boolean[].class;
} else if (rst == RST_BYTES) {
return byte[].class;
} else if (rst == RST_CHARS) {
return char[].class;
} else if (rst == RST_SHORTS) {
return short[].class;
} else if (rst == RST_INTS) {
return int[].class;
} else if (rst == RST_LONGS) {
return long[].class;
} else if (rst == RST_FLOATS) {
return float[].class;
} else if (rst == RST_DOUBLES) {
return double[].class;
} else if (rst == RST_PROTOCOL) {
return Protocol.class;
}
} else if (rt == RT_MULTI) {
if (rst == RST_BOOLEAN) {
return Boolean[].class;
} else if (rst == RST_BYTE) {
return Byte[].class;
} else if (rst == RST_CHARACTER) {
return Character[].class;
} else if (rst == RST_SHORT) {
return Short[].class;
} else if (rst == RST_INTEGER) {
return Integer[].class;
} else if (rst == RST_LONG) {
return Long[].class;
} else if (rst == RST_FLOAT) {
return Float[].class;
} else if (rst == RST_DOUBLE) {
return Double[].class;
} else if (rst == RST_STRING) {
return String[].class;
} else if (rst == RST_BOOLEANS) {
return boolean[][].class;
} else if (rst == RST_BYTES) {
return byte[][].class;
} else if (rst == RST_CHARS) {
return char[][].class;
} else if (rst == RST_SHORTS) {
return short[][].class;
} else if (rst == RST_INTS) {
return int[][].class;
} else if (rst == RST_LONGS) {
return long[][].class;
} else if (rst == RST_FLOATS) {
return float[][].class;
} else if (rst == RST_DOUBLES) {
return double[][].class;
} else if (rst == RST_PROTOCOL) {
return Protocol[].class;
} else {
return Object[].class;
}
}
}
return null;
}
public static Protocol deserializeProtocol(byte[] b, int off, int[] outLen) throws IOException, InstantiationException, ClassNotFoundException {
if (b == null) {
throw new NullPointerException();
}
if (off < 0) {
throw new IllegalArgumentException();
}
if (off >= b.length) {
throw new IllegalArgumentException();
}
MemoryStream ms = new MemoryStream();
ms.write(b, off, b.length - off);
Length length = ms.readLength();
String typeNameExpr = ms.readBytes(length.intValue());
String[] typeNameExprEntries = typeNameExpr.split(";");
List<Class<?>> typeList = new ArrayList<Class<?>>();
List<Length> objectCounts = new ArrayList<Length>();
for (String typeNameExprEntry : typeNameExprEntries) {
int index = typeNameExprEntry.lastIndexOf('$');
if (index < 0) {
index = typeNameExprEntry.lastIndexOf('.');
}
index += 1;
String commonTypeNamePrefix = typeNameExprEntry.substring(0, index);
String simpleTypeNameExpr = typeNameExprEntry.substring(index);
String[] simpleTypeNames = simpleTypeNameExpr.split(",");
for (String simpleTypeName : simpleTypeNames) {
typeList.add(Class.forName(commonTypeNamePrefix + simpleTypeName));
}
}
for (Class<?> type : typeList) {
Length objCount = ms.readLength();
objectCounts.add(objCount);
}
List<Protocol> protocolsInOrder = new ArrayList<Protocol>();
for (int i = 0; i < typeList.size(); i++) {
Class<?> type = typeList.get(i);
Length objCount = objectCounts.get(i);
for (int j = 0; j < objCount.intValue(); j++) {
Protocol protocolInOrder = (Protocol )newLocalProtocol(type);
protocolsInOrder.add(protocolInOrder);
}
}
for (Protocol protocolInOrder : protocolsInOrder) {
ProtocolInvocationHandler pih = (ProtocolInvocationHandler )Proxy.getInvocationHandler(protocolInOrder);
readSingleObject(ms, protocolInOrder, pih.getProtocolType(), protocolsInOrder);
}
// Protocol finalProtocol = protocolsInOrder.get(ms.readLength().intValue());
System.out.println("AVAILABLE = " + ms.available());
// return finalProtocol;
return protocolsInOrder.get(0);
}
private static Protocol readSingleObject(MemoryStream ms, Protocol protocol, Class<?> type, List<Protocol> protocolsInOrder) throws InstantiationException, IOException {
ProtocolInvocationHandler pih = (ProtocolInvocationHandler )Proxy.getInvocationHandler(protocol);
Map<String, Object> propertyMap = pih.getPropertyMap();
for (String key : propertyMap.keySet()) {
Method[] methods = type.getMethods();
String set = "set" + Character.toUpperCase(key.charAt(0)) + key.substring(1);
String coll = key;
boolean isColl = false;
Method theMethod = null;
Class<?> theType = null;
for (Method method : methods) {
if (method.getName().equals(set)) {
theMethod = method;
theType = theMethod.getParameterTypes()[0];
} else if (method.getName().equals(coll)) {
theMethod = method;
theType = method.getReturnType();
isColl = true;
}
}
if (theMethod == null || theType == null) {
throw new IOException("Object is corrupted.");
}
try {
if (isColl) {
ProtocolCollection pc = (ProtocolCollection )theMethod.invoke(protocol);
if (pc instanceof ProtocolSet) {
ProtocolSet ps = (ProtocolSet )pc;
Length length = ms.readLength();
for (int i = 0; i < length.intValue(); i++) {
ps.add(readSingleValue(ms, Object.class, protocolsInOrder));
}
} else if (pc instanceof ProtocolMap) {
ProtocolMap pm = (ProtocolMap )pc;
Length length = ms.readLength();
for (int i = 0; i < length.intValue(); i++) {
Object k = readSingleValue(ms, Object.class, protocolsInOrder);
Object v = readSingleValue(ms, Object.class, protocolsInOrder);
pm.put(k, v);
}
}
} else {
try {
theMethod.invoke(protocol, readSingleValue(ms, theType, protocolsInOrder));
} catch (Exception ex) {
throw new IOException(ex);
}
}
} catch (Exception ex) {
throw new IOException(ex);
}
}
return protocol;
}
private static void fillProtocolObjectMap(Object current, SortedMap<Class<?>, SortedSet<Protocol>> protocolObjectMap) {
if (protocolObjectMap == null) {
throw new NullPointerException();
}
if (current == null) {
return;
}
if (current instanceof Protocol) {
Protocol protocol = (Protocol )current;
ProtocolInvocationHandler pih = (ProtocolInvocationHandler )Proxy.getInvocationHandler(protocol);
if (pih == null) {
throw new IllegalArgumentException();
}
Class<?> protocolType = pih.getProtocolType();
SortedSet<Protocol> protocolObjectSet = getProtocolObjectSet(protocolObjectMap, protocolType);
if (protocolObjectSet.add(protocol)) {
Map<String, Object> propertyMap = pih.getPropertyMap();
for (Object value : propertyMap.values()) {
fillProtocolObjectMap(value, protocolObjectMap);
}
}
} else if (current instanceof ProtocolSet) {
ProtocolSet<?> protocolSet = (ProtocolSet<?> )current;
Object[] array = protocolSet.toArray();
for (Object item : array) {
fillProtocolObjectMap(item, protocolObjectMap);
}
} else if (current instanceof ProtocolMap) {
ProtocolMap<?, ?> protocolMap = (ProtocolMap<?, ?> )current;
Object[] keys = protocolMap.keys();
for (Object key : keys) {
fillProtocolObjectMap(key, protocolObjectMap);
fillProtocolObjectMap(protocolMap.get(key), protocolObjectMap);
}
} else {
Class<?> type = current.getClass();
if (type.isArray()) {
for (int i = 0; i < Array.getLength(current); i++) {
Object item = Array.get(current, i);
fillProtocolObjectMap(item, protocolObjectMap);
}
}
}
}
private static SortedSet<Protocol> getProtocolObjectSet(SortedMap<Class<?>, SortedSet<Protocol>> protocolObjectMap, Class<?> type) {
if (protocolObjectMap == null) {
throw new NullPointerException();
}
if (type == null) {
throw new NullPointerException();
}
SortedSet<Protocol> protocolObjectSet = protocolObjectMap.get(type);
if (protocolObjectSet == null) {
Comparator<Protocol> protocolComparator = new Comparator<Protocol>() {
@Override
public int compare(Protocol protocol0, Protocol protocol1) {
int hashCode0 = protocol0.hashCode();
int hashCode1 = protocol1.hashCode();
return hashCode0 - hashCode1;
}
};
protocolObjectSet = new TreeSet<Protocol>(protocolComparator);
protocolObjectMap.put(type, protocolObjectSet);
}
return protocolObjectSet;
}
private static SortedSet<String> getSimpleTypeNameSet(SortedMap<String, SortedSet<String>> typeNameMap, String commonTypeNamePrefix) {
if (typeNameMap == null) {
throw new NullPointerException();
}
if (commonTypeNamePrefix == null) {
throw new NullPointerException();
}
if (commonTypeNamePrefix.isEmpty()) {
throw new IllegalArgumentException();
}
SortedSet<String> simpleTypeNameSet = typeNameMap.get(commonTypeNamePrefix);
if (simpleTypeNameSet == null) {
simpleTypeNameSet = new TreeSet<String>();
typeNameMap.put(commonTypeNamePrefix, simpleTypeNameSet);
}
return simpleTypeNameSet;
}
public static boolean isEmpty(String str) {
if (str == null) {
return true;
}
return str.isEmpty();
}
public static interface WhiteboardDocument extends Protocol {
String getId();
void setId(String value);
String getName();
void setName(String value);
ProtocolMap<String, Object> authorProperties();
ProtocolList<WhiteboardWorksheet> worksheets();
}
public static interface WhiteboardWorksheet extends Protocol {
String getName();
void setName(String value);
ProtocolList<WhiteboardObject> objects();
}
@Abstract
public static interface WhiteboardObject extends Protocol {
String getId();
void setId(String value);
String getName();
void setName(String value);
String[] getDescLines();
void setDescLines(String[] value);
}
@Abstract
public static interface WhiteboardVisualObject extends WhiteboardObject {
WhiteboardPen getPen();
void setPen(WhiteboardPen value);
WhiteboardBrush[] getBrushes();
void setBrushes(WhiteboardBrush[] values);
}
public static interface WhiteboardRectangle extends WhiteboardVisualObject {
int getX();
void setX(int value);
int getY();
void setY(int value);
int getWidth();
void setWidth(int value);
int getHeight();
void setHeight(int value);
}
public static interface WhiteboardPen extends Protocol {
int getWidth();
void setWidth(int value);
WhiteboardColor getColor();
void setColor(WhiteboardColor value);
}
public static interface WhiteboardBrush extends Protocol {
WhiteboardColor getColor();
void setColor(WhiteboardColor value);
}
public static interface WhiteboardColor extends Protocol {
int[] getRgb();
void setRgb(int[] value);
}
public static interface Data extends Protocol {
boolean isBoolean();
void setBoolean(boolean value);
byte getByte();
void setByte(byte value);
char getChar();
void setChar(char value);
short getShort();
void setShort(short value);
int getInt();
void setInt(int value);
long getLong();
void setLong(long value);
float getFloat();
void setFloat(float value);
double getDouble();
void setDouble(double value);
Boolean getBooleanObject();
void setBooleanObject(Boolean value);
Byte getByteObject();
void setByteObject(Byte value);
Character getCharacterObject();
void setCharacterObject(Character value);
Short getShortObject();
void setShortObject(Short value);
Integer getIntegerObject();
void setIntegerObject(Integer value);
Long getLongObject();
void setLongObject(Long value);
Float getFloatObject();
void setFloatObject(Float value);
Double getDoubleObject();
void setDoubleObject(Double value);
Boolean getNullBooleanObject();
void setNullBooleanObject(Boolean value);
Byte getNullByteObject();
void setNullByteObject(Byte value);
Character getNullCharacterObject();
void setNullCharacterObject(Character value);
Short getNullShortObject();
void setNullShortObject(Short value);
Integer getNullIntegerObject();
void setNullIntegerObject(Integer value);
Long getNullLongObject();
void setNullLongObject(Long value);
Float getNullFloatObject();
void setNullFloatObject(Float value);
Double getNullDoubleObject();
void setNullDoubleObject(Double value);
boolean[] getBooleanArray();
void setBooleanArray(boolean[] value);
byte[] getByteArray();
void setByteArray(byte[] value);
String[] getStringArray();
void setStringArray(String[] value);
Double[][] getDoubleArray();
void setDoubleArray(Double[][] value);
boolean[] getNullBooleanArray();
void setNullBooleanArray(boolean[] value);
byte[] getNullByteArray();
void setNullByteArray(byte[] value);
String[] getNullStringArray();
void setNullStringArray(String[] value);
Double[][] getNullDoubleArray();
void setNullDoubleArray(Double[][] value);
boolean[] getEmptyBooleanArray();
void setEmptyBooleanArray(boolean[] value);
byte[] getEmptyByteArray();
void setEmptyByteArray(byte[] value);
String[] getEmptyStringArray();
void setEmptyStringArray(String[] value);
Double[][] getPartialEmptyDoubleArray();
void setPartialEmptyDoubleArray(Double[][] value);
Double[][] getEmptyDoubleArray();
void setEmptyDoubleArray(Double[][] value);
Object getSingleObject();
void setSingleObject(Object value);
Object getMultiObject();
void setMultiObject(Object value);
ProtocolSet<Object> set();
ProtocolList<Object> list();
Data getSelf();
void setSelf(Data value);
}
interface Foo extends Protocol {
Object getA();
void setA(Object value);
}
interface Bar extends Protocol {
Object getA();
void setA(Object value);
}
interface FooBar extends Protocol {
FooBar getSelf();
void setSelf(FooBar value);
Object getSelf2();
void setSelf2(Object value);
FooBar[] getSelves();
void setSelves(FooBar[] value);
Object[] getSelves2();
void setSelves2(Object[] value);
FooBar[][] getDeep();
void setDeep(FooBar[][] value);
Object[][] getDeepObj();
void setDeepObj(Object[][] value);
ProtocolSet<Object> selfSet();
ProtocolList<Object> selfList();
ProtocolMap<Object, Object> selfMap();
}
interface Person extends Protocol {
String getName();
void setName(String value);
Person getSpouse();
void setSpouse(Person value);
}
public static void main(String[] args) throws Exception {
// test1();
// Person a0 = newLocalProtocol(Person.class);
// Person b0 = newLocalProtocol(Person.class);
//
// a0.setName("John");
// b0.setName("Lisa");
//
// a0.setSpouse(b0);
// b0.setSpouse(a0);
//
// byte[] data = serializeProtocol(a0);
//
// Person x = (Person )deserializeProtocol(data, 0, null);
//
// System.out.println(a0 + ", " + b0 + ", " + x.getName() + ", " + x.getSpouse().getName());
// FooBar fb0 = newLocalProtocol(FooBar.class);
// fb0.setSelf(fb0);
// fb0.setSelf2(fb0);
// fb0.setSelves(new FooBar[] { fb0 });
// fb0.setSelves2(new Object[] { fb0 });
// fb0.setDeep(new FooBar[][] { null, new FooBar[0], new FooBar[] { fb0 } });
// fb0.setDeepObj(new Object[][] { null, new Object[0], new Object[] { fb0 } });
// fb0.selfSet().add(fb0);
// fb0.selfList().add(fb0);
// fb0.selfMap().put("Hello World!", fb0);
// byte[] bytes = serializeProtocol(fb0);
// FooBar fb1 = (FooBar )deserializeProtocol(bytes, 0, null);
// System.out.println(fb1 + " == " + fb1.getSelf() + " == " + fb1.getSelf2() + " == " +
// Arrays.deepToString((Object[] )fb1.getSelves()) + " == " + Arrays.deepToString((Object[] )fb1.getSelves2()) + " == " +
// fb1.selfSet() + " == " + fb1.selfList() + " == " + Arrays.deepToString((Object[] )fb1.getDeep()) + " == " +
// Arrays.deepToString((Object[] )fb1.getDeepObj()) + " == " + Arrays.toString(fb0.selfMap().keys()) + " == " +
// Arrays.toString(fb1.selfMap().values()));
// Bar bar0 = newLocalProtocol(Bar.class);
// bar0.setA(new Object[][] { null, new Object[] { 1.0, 2.0 }, new Object[0], new Object[] { 3.0 } });
// byte[] bytes = serializeProtocol(bar0);
// Bar bar1 = (Bar )deserializeProtocol(bytes, 0, null);
// System.out.println(Arrays.deepToString((Object[] )bar1.getA()));
// Foo foo0 = newLocalProtocol(Foo.class);
// foo0.setA(new Integer[] { 1, 2, 3 });
// byte[] bytes = serializeProtocol(foo0);
// Foo foo1 = (Foo )deserializeProtocol(bytes, 0, null);
// System.out.println(Arrays.deepToString((Object[] )foo1.getA()));
// WhiteboardDocument doc0 = initializeWhiteboardDocument();
// byte[] bytes = serializeProtocol(doc0);
// WhiteboardDocument doc = (WhiteboardDocument )deserializeProtocol(bytes, 0, null);
// System.out.println(doc);
}
private static void test1() throws Exception {
Data data0 = newLocalProtocol(Data.class);
data0.setBoolean(true);
data0.setByte(Byte.MAX_VALUE);
data0.setChar('A');
data0.setShort(Short.MAX_VALUE);
data0.setInt(Integer.MAX_VALUE);
data0.setLong(Long.MAX_VALUE);
data0.setFloat(Float.MAX_VALUE);
data0.setDouble(Double.MAX_VALUE);
data0.setBooleanObject(Boolean.TRUE);
data0.setByteObject(Byte.MAX_VALUE);
data0.setCharacterObject('A');
data0.setShortObject(Short.MAX_VALUE);
data0.setIntegerObject(Integer.MAX_VALUE);
data0.setLongObject(Long.MAX_VALUE);
data0.setFloatObject(Float.MAX_VALUE);
data0.setDoubleObject(Double.MAX_VALUE);
data0.setBooleanArray(new boolean[] { true, false, true, false, true, false, true, false, true });
data0.setByteArray(new byte[] { 1, 2, 3, 4, 5 });
data0.setStringArray(new String[] { "Hello", "World", "!", "Hello World!" });
data0.setDoubleArray(new Double[][] { new Double[] { 1.0, 2.0, 3.0 }, new Double[] { 4.0, 5.0 }, new Double[] { 6.0 } });
data0.setEmptyBooleanArray(new boolean[0]);
data0.setEmptyByteArray(new byte[0]);
data0.setEmptyStringArray(new String[0]);
data0.setPartialEmptyDoubleArray(new Double[][] { new Double[] { 1.0 }, new Double[0], null, new Double[] { 2.0, 3.0 } });
data0.setEmptyDoubleArray(new Double[0][]);
data0.set().add(true);
data0.set().add('A');
data0.set().add(Integer.MAX_VALUE);
data0.set().add(Double.MAX_VALUE);
data0.set().add(new boolean[] { true, false, true, false, true, false, true, false, false, true });
data0.list().add(Byte.MAX_VALUE);
data0.list().add(Short.MAX_VALUE);
data0.list().add(Float.MAX_VALUE);
data0.list().add("Hello World!");
data0.list().add(new Object[][] { null, new Object[] { 3.0, 8.0 }, new Object[0], new Object[] { 1.0 } });
data0.list().add(new Double[] { null, 2.0, 3.0 });
data0.setSelf(data0);
// data0.setSingleObject(true);
// data0.setSingleObject(Byte.MAX_VALUE);
// data0.setSingleObject('A');
// data0.setSingleObject(Short.MAX_VALUE);
// data0.setSingleObject(Integer.MAX_VALUE);
// data0.setSingleObject(Long.MAX_VALUE);
// data0.setSingleObject(Float.MAX_VALUE);
// data0.setSingleObject(Double.MAX_VALUE);
// data0.setSingleObject("Hello World!");
// data0.setSingleObject(new boolean[] { true, false, true });
data0.setSingleObject(new double[] { 1.0, 2.0, 3.0 });
data0.setMultiObject(new Integer[] { 1, 2, 3 });
byte[] bytes = serializeProtocol(data0);
Data data1 = (Data )deserializeProtocol(bytes, 0, null);
System.out.println("boolean = " + data1.isBoolean());
System.out.println("byte = " + data1.getByte());
System.out.println("char = " + data1.getChar());
System.out.println("short = " + data1.getShort());
System.out.println("int = " + data1.getInt());
System.out.println("long = " + data1.getLong());
System.out.println("float = " + data1.getFloat());
System.out.println("double = " + data1.getDouble());
System.out.println("Boolean = " + data1.getBooleanObject());
System.out.println("Byte = " + data1.getByteObject());
System.out.println("Character = " + data1.getCharacterObject());
System.out.println("Short = " + data1.getShortObject());
System.out.println("Integer = " + data1.getIntegerObject());
System.out.println("Long = " + data1.getLongObject());
System.out.println("Float = " + data1.getFloatObject());
System.out.println("Double = " + data1.getDoubleObject());
System.out.println("NullBoolean = " + data1.getNullBooleanObject());
System.out.println("NullByte = " + data1.getNullByteObject());
System.out.println("NullCharacter = " + data1.getNullCharacterObject());
System.out.println("NullShort = " + data1.getNullShortObject());
System.out.println("NullInteger = " + data1.getNullIntegerObject());
System.out.println("NullLong = " + data1.getNullLongObject());
System.out.println("NullFloat = " + data1.getNullFloatObject());
System.out.println("NullDouble = " + data1.getNullDoubleObject());
System.out.println("boolean array = " + Arrays.toString(data1.getBooleanArray()));
System.out.println("byte array = " + Arrays.toString(data1.getByteArray()));
System.out.println("String array = " + Arrays.toString(data1.getStringArray()));
System.out.println("Double array = " + Arrays.deepToString(data1.getDoubleArray()));
System.out.println("null boolean array = " + data1.getNullBooleanArray());
System.out.println("null byte array = " + data1.getNullByteArray());
System.out.println("null String array = " + data1.getNullStringArray());
System.out.println("null Double array = " + data1.getNullDoubleArray());
System.out.println("empty boolean array = " + Arrays.toString(data1.getEmptyBooleanArray()));
System.out.println("empty byte array = " + Arrays.toString(data1.getEmptyByteArray()));
System.out.println("empty String array = " + Arrays.toString(data1.getEmptyStringArray()));
System.out.println("parital empty Double array = " + Arrays.deepToString(data1.getPartialEmptyDoubleArray()));
System.out.println("empty Double array = " + Arrays.deepToString(data1.getEmptyDoubleArray()));
// System.out.println("single object = " + data1.getSingleObject());
// System.out.println("single object = " + Arrays.toString((boolean[] )data1.getSingleObject()));
System.out.println("single object = " + Arrays.toString((double[] )data1.getSingleObject()));
System.out.println("multi object = " + Arrays.deepToString((Object[] )data1.getMultiObject()));
System.out.println("set count = " + data1.set().size());
System.out.println("set values = " + Arrays.deepToString(data1.set().toArray()));
System.out.println("list count = " + data1.list().size());
System.out.println("list values = " + Arrays.deepToString(data1.list().toArray()));
System.out.println("runtime dynamically typed type = " + Arrays.toString((Object[] )data1.list().get(5)));
}
private static WhiteboardDocument initializeWhiteboardDocument() throws Exception {
WhiteboardDocument doc = newLocalProtocol(WhiteboardDocument.class);
{
doc.setId("document1");
doc.setName("Document One");
WhiteboardPen defaultPen = newLocalProtocol(WhiteboardPen.class);
{
defaultPen.setWidth(5);
WhiteboardColor defaultPenColor = newLocalProtocol(WhiteboardColor.class);
{
defaultPenColor.setRgb(new int[] { 1, 0, 0 });
}
defaultPen.setColor(defaultPenColor);
}
doc.authorProperties().put("defaultPen", defaultPen);
WhiteboardBrush defaultBrush0 = newLocalProtocol(WhiteboardBrush.class);
{
WhiteboardColor defaultBrushColor0 = newLocalProtocol(WhiteboardColor.class);
{
defaultBrushColor0.setRgb(new int[] { 255, 255, 255 });
}
defaultBrush0.setColor(defaultBrushColor0);
}
WhiteboardBrush defaultBrush1 = newLocalProtocol(WhiteboardBrush.class);
{
WhiteboardColor defaultBrushColor1 = newLocalProtocol(WhiteboardColor.class);
{
defaultBrushColor1.setRgb(new int[] { 128, 128, 128 });
}
defaultBrush1.setColor(defaultBrushColor1);
}
doc.authorProperties().put("defaultBrushes", new Object[] { defaultBrush0, defaultBrush1 });
Sample sample = newLocalProtocol(Sample.class);
Sample.Foo foo = newLocalProtocol(Sample.Foo.class);
doc.authorProperties().put("objects", new Object[] { defaultBrush0, defaultPen, doc, sample, foo });
doc.authorProperties().put("author", "hytparadisee");
doc.authorProperties().put("pointback", doc);
WhiteboardWorksheet sheet0 = newLocalProtocol(WhiteboardWorksheet.class);
{
sheet0.setName("Sheet 1");
WhiteboardRectangle rect0 = newLocalProtocol(WhiteboardRectangle.class);
{
rect0.setId("rect0");
rect0.setName("Rectangle 0");
rect0.setDescLines(new String[] { "A small rectangle", "Nothing special", "Yet important" });
rect0.setX(0);
rect0.setY(0);
rect0.setWidth(200);
rect0.setHeight(100);
}
sheet0.objects().add(rect0);
WhiteboardRectangle rect1 = newLocalProtocol(WhiteboardRectangle.class);
{
rect1.setId("rect1");
rect1.setName("Another beautiful rectangle");
rect1.setDescLines(new String[] { null, null, "Haha!" });
rect1.setX(300);
rect1.setY(45);
rect1.setWidth(200);
rect1.setHeight(40);
WhiteboardBrush rectBrush0 = newLocalProtocol(WhiteboardBrush.class);
{
WhiteboardColor rectBrushColor0 = newLocalProtocol(WhiteboardColor.class);
{
rectBrushColor0.setRgb(new int[] { 255, 0, 0 });
}
rectBrush0.setColor(rectBrushColor0);
}
rect1.setBrushes(new WhiteboardBrush[] { rectBrush0 });
}
sheet0.objects().add(rect1);
}
doc.worksheets().add(sheet0);
WhiteboardWorksheet sheet1 = newLocalProtocol(WhiteboardWorksheet.class);
{
sheet1.setName("My Sheet");
}
doc.worksheets().add(sheet1);
WhiteboardWorksheet sheet2 = newLocalProtocol(WhiteboardWorksheet.class);
{
sheet2.setName("Custom Sheet");
WhiteboardRectangle rect0 = newLocalProtocol(WhiteboardRectangle.class);
{
rect0.setId("rect1");
rect0.setName("A rect in sheet 2");
rect0.setDescLines(new String[] { "Some description" });
rect0.setX(50);
rect0.setY(50);
rect0.setWidth(50);
rect0.setHeight(50);
WhiteboardPen rectPen = newLocalProtocol(WhiteboardPen.class);
{
WhiteboardColor rectPenColor = newLocalProtocol(WhiteboardColor.class);
{
rectPenColor.setRgb(new int[] { 0, 255, 0 });
}
rectPen.setColor(rectPenColor);
}
rect0.setPen(rectPen);
}
sheet2.objects().add(rect0);
}
doc.worksheets().add(sheet2);
}
return doc;
}
}