package net.carchrae.smartgwt.server;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.Id;
import net.carchrae.smartgwt.client.datasource.DataSourceService;
import net.carchrae.smartgwt.shared.data.DataSourceDescriptor;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.googlecode.objectify.impl.TypeUtils;
@SuppressWarnings("serial")
public class DataSourceServiceImpl extends RemoteServiceServlet implements
DataSourceService {
HashMap<String, Class<?>> classMap = new HashMap<String, Class<?>>();
HashMap<String, DataSourceDescriptor> dataSourceMap = new HashMap<String, DataSourceDescriptor>();;
public DataSourceServiceImpl() {
// This registers our datasource names, more than one name per class if
// you like
for (Class<?> c : DataStoreService.getClasses()) {
String shortName = c.getSimpleName();
String name = c.getName();
classMap.put(shortName.toLowerCase(), c);
classMap.put(name, c);
}
}
@Override
public DataSourceDescriptor getDataSource(String name) {
DataSourceDescriptor descriptor = dataSourceMap.get(name);
if (descriptor == null) {
Class<?> class1 = classMap.get(name.toLowerCase());
if (class1 != null)
dataSourceMap.put(name,
descriptor = createDataSourceDescriptor(class1));
}
return descriptor;
}
private DataSourceDescriptor createDataSourceDescriptor(Class<?> clazz) {
DataSourceDescriptor dataSourceDescriptor = new DataSourceDescriptor();
String name = clazz.getSimpleName().toLowerCase();
dataSourceDescriptor.put("name", name);
// dataSourceDescriptor.put("dataFormat", DSDataFormat.JSON.getValue());
dataSourceDescriptor.put("dataFormat", "json");
for (Field field : clazz.getDeclaredFields()) {
if (!TypeUtils.isSaveable(field))
continue;
boolean original = field.isAccessible();
field.setAccessible(true);
String fieldName = field.getName();
Map<String, String> map = new HashMap<String, String>();
dataSourceDescriptor.getFields().put(fieldName, map);
System.out.println("getting type for " + fieldName + " "
+ field.getType().getSimpleName());
String fieldType;
if (isCollection(field.getType())) {
map.put("multiple", "true");
fieldType = convertToDataSourceFieldType((Class<?>) getTypeInCollection(field));
} else
fieldType = convertToDataSourceFieldType(field.getType());
map.put("type", fieldType);
if (field.isAnnotationPresent(Id.class)) {
map.put("primaryKey", "true");
dataSourceDescriptor.setId(fieldName);
}
field.setAccessible(original);
}
return dataSourceDescriptor;
}
private Class<?> getTypeInCollection(Field field) {
ParameterizedType paramType = (ParameterizedType) field
.getGenericType();
Class<?> listClass = (Class<?>) paramType.getActualTypeArguments()[0];
System.out.println(listClass); // class java.lang.String.
return listClass;
}
private boolean isCollection(Class<?> type) {
if (Collection.class.isAssignableFrom(type))
return true;
else
return false;
}
private String convertToDataSourceFieldType(Class<?> type) {
if (isCollection(type))
type = getContainedType((Class<? extends Collection>) type);
if (Long.class.isAssignableFrom(type))
return "sequence";
if (Integer.class.isAssignableFrom(type))
return "integer";
if (String.class.isAssignableFrom(type))
return "text";
if (Date.class.isAssignableFrom(type))
return "date";
if (Boolean.class.isAssignableFrom(type))
return "boolean";
return null;
}
private Class<?> getContainedType(Class<? extends Collection> type) {
// find the add method
System.out.println("trying to get params for " + type.getName() + " ");
for (Method m : type.getMethods()) {
if ("add".equals(m.getName())) {
Type[] types = m.getGenericParameterTypes();
Type type3 = types[0];
if (type3 instanceof ParameterizedType) {
ParameterizedType type2 = (ParameterizedType) type3;
Class<?> containedClass = (Class<?>) type2
.getActualTypeArguments()[0];
return containedClass;
} else if (type3 instanceof TypeVariable) {
TypeVariable t = (TypeVariable) type3;
GenericDeclaration genericDeclaration = t
.getGenericDeclaration();
TypeVariable<?>[] typeParameters = genericDeclaration
.getTypeParameters();
TypeVariable<?> t2 = typeParameters[0];
}
}
}
throw new RuntimeException("No generic type info for " + type.getName());
// Field stringListField = Test.class.getDeclaredField("stringList");
// ParameterizedType stringListType = (ParameterizedType)
// stringListField
// .getGenericType();
// Class<?> stringListClass = (Class<?>) stringListType
// .getActualTypeArguments()[0];
// System.out.println(stringListClass); // class java.lang.String.
// return
// // null;
}
}