package net.techreadiness.ui.util;
import java.lang.reflect.Member;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.servlet.ServletContext;
import net.techreadiness.persistence.AuditedBaseEntity;
import net.techreadiness.service.object.BaseObject;
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.conversion.TypeConverter;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Inject;
public class ReadinessTypeConverterFactory extends XWorkConverter implements Function<String, TypeConverter> {
/** Null object we will return from the lookup cache since ComputingMap does not cache null values **/
private static final TypeConverter NONE = new TypeConverter() {
@Override
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName,
Object value, Class toType) {
return null;
}
};
private BaseEntityTypeConverter baseEntityTypeConverter;
private ServiceObjectTypeConverter baseObjectTypeConverter;
private LoadingCache<String, TypeConverter> lookupCache;
private TextProvider textProvider;
@Inject
public ReadinessTypeConverterFactory(ServletContext servletContext) {
baseEntityTypeConverter = ContextUtils.getRequiredBeanOfType(BaseEntityTypeConverter.class, servletContext);
baseObjectTypeConverter = ContextUtils.getRequiredBeanOfType(ServiceObjectTypeConverter.class, servletContext);
lookupCache = CacheBuilder.newBuilder().build(CacheLoader.from(this));
}
@Override
public TypeConverter lookup(String className) {
TypeConverter typeConverter;
try {
typeConverter = lookupCache.get(className);
if (typeConverter != NONE) {
return typeConverter;
}
} catch (ExecutionException e) {
// Ignore failure
}
return super.lookup(className);
}
@Override
public TypeConverter apply(String className) {
try {
Class<?> clas = Class.forName(className);
if (AuditedBaseEntity.class.isAssignableFrom(clas)) {
return baseEntityTypeConverter;
} else if (BaseObject.class.isAssignableFrom(clas)) {
return baseObjectTypeConverter;
} else if (Date.class.isAssignableFrom(clas)) {
return new ConfigurableDateConverter(textProvider);
}
} catch (ClassNotFoundException ignore) {
// Ignore failure
}
return NONE;
}
public TextProvider getTextProvider() {
return textProvider;
}
@Inject
public void setTextProvider(TextProvider textProvider) {
this.textProvider = textProvider;
}
}