Created
December 8, 2009 20:42
-
-
Save iamnoah/251982 to your computer and use it in GitHub Desktop.
DWR converter for Grails ORM classes. Uses the hasMany map to determine the type of collections so we can convert them inbound.
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.noahsloan.grails.dwr; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.util.Collection; | |
import java.util.Map; | |
import org.directwebremoting.convert.BeanConverter; | |
import org.directwebremoting.convert.CollectionConverter; | |
import org.directwebremoting.extend.InboundContext; | |
import org.directwebremoting.extend.Property; | |
import org.directwebremoting.extend.TypeHintContext; | |
import org.directwebremoting.util.Logger; | |
import com.sun.tools.jdi.LinkedHashMap; | |
/** | |
* Converter for Grails ORM classes. Uses the hasMany map to determine the type | |
* of collections so we can convert them inbound. | |
* | |
* @author noah | |
* | |
*/ | |
@SuppressWarnings("unchecked") | |
public class DwrGormConverter extends BeanConverter { | |
private static final Logger LOG = org.directwebremoting.util.Logger | |
.getLogger(DwrGormConverter.class); | |
protected TypeHintContext createTypeHintContext(InboundContext inctx, | |
final Property property) { | |
// check collections | |
if (Collection.class.isAssignableFrom(property.getPropertyType())) { | |
final Class type = getCollectionType(property); | |
if (type != null) { | |
return createHint(property.getSetter(), type); | |
} | |
} | |
return super.createTypeHintContext(inctx, property); | |
} | |
/** | |
* Pulled out for readability. Creates a type hint for the | |
* {@link CollectionConverter} with the given type. | |
* | |
* @param setter TODO is this necessary? | |
* @param type | |
* @return | |
*/ | |
protected TypeHintContext createHint(final Method setter, | |
final Class type) { | |
return new TypeHintContext(converterManager, setter, 0) { | |
public TypeHintContext createChildContext(int newParameterNumber) { | |
return new TypeHintContext(converterManager, setter, 0) { | |
public Class getExtraTypeInfo() { | |
return type; | |
} | |
}; | |
} | |
}; | |
} | |
protected static Map<Class, Map<String, Class>> _cache = new LinkedHashMap(); | |
/** | |
* Determines the type of the collection by examining the declaring class' | |
* static hasMany property. | |
* | |
* @param property | |
* @return the type of the elements of the collection property. | |
*/ | |
protected Class getCollectionType(Property property) { | |
// determine the class the collection is attached to by examining | |
// the setter (which is the domain class) | |
Method setter = property.getSetter(); | |
if (setter == null) { | |
// XXX in theory this should not happen because BeanConverter should | |
// always provide PropertyDescriptionPropertys | |
LOG.error("setter for " | |
+ property.getName() + " is null." | |
+ " Property is not a PropertyDescriptionProperty."); | |
return null; | |
} | |
Class gormType = setter.getDeclaringClass(); | |
if (_cache.containsKey(gormType)) { | |
Map<String, Class> map = _cache.get(gormType); | |
return map == null ? null : map.get(property.getName()); | |
} | |
try { | |
Field field = gormType.getDeclaredField("hasMany"); | |
Map<String, Class> map = null; | |
if (field != null) { | |
if (!field.isAccessible()) { | |
field.setAccessible(true); | |
} | |
map = ((Map<String, Class>) field.get(null)); | |
} | |
_cache.put(gormType, map); | |
return map == null ? null : map.get(property.getName()); | |
} catch (Exception e) { | |
LOG.error("Exception getting GORM collection type info.", e); | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment