package com.aggrepoint.winlet.spring;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.format.AnnotationFormatterFactory;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.util.StringValueResolver;
import com.aggrepoint.winlet.ContextUtils;
public class WinletDefaultFormattingConversionService extends
DefaultFormattingConversionService {
private HashSet<Class<? extends Annotation>> fmtAnnotations;
private HashSet<Class<? extends Annotation>> getFmtAnnotations() {
if (fmtAnnotations == null)
fmtAnnotations = new HashSet<Class<? extends Annotation>>();
return fmtAnnotations;
}
public WinletDefaultFormattingConversionService(
StringValueResolver embeddedValueResolver,
boolean registerDefaultFormatters) {
super(embeddedValueResolver, registerDefaultFormatters);
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public void addFormatterForFieldAnnotation(
AnnotationFormatterFactory annotationFormatterFactory) {
Class<? extends Annotation> annotationType = (Class<? extends Annotation>) GenericTypeResolver
.resolveTypeArgument(annotationFormatterFactory.getClass(),
AnnotationFormatterFactory.class);
if (annotationType != null)
getFmtAnnotations().add(annotationType);
super.addFormatterForFieldAnnotation(annotationFormatterFactory);
}
public boolean hasFmtAnnotation(TypeDescriptor td) {
for (Annotation ann : td.getAnnotations())
if (getFmtAnnotations().contains(ann.annotationType()))
return true;
return false;
}
// ////////////////////////////////////////
//
// 以下方法供Winlet模块直接调用
//
// ////////////////////////////////////////
static HashMap<String, Boolean> cache = new HashMap<String, Boolean>();
public static WinletDefaultFormattingConversionService get() {
Map<String, ConversionService> css = ContextUtils
.getApplicationContext(ContextUtils.getRequest())
.getBeansOfType(ConversionService.class);
if (css == null || css.size() == 0)
return null;
for (ConversionService cs : css.values())
if (cs instanceof WinletDefaultFormattingConversionService)
return (WinletDefaultFormattingConversionService) cs;
return null;
}
/**
* 判断对象属性是否有格式可以应用。调用format()前必须先调用canFormat()
*
* @param obj
* @param prop
* @return
*/
public static boolean canFormat(ConfigurablePropertyAccessor bw,
Object obj, String prop) {
String key = obj.getClass().getName() + "_" + prop;
if (!cache.containsKey(key)) {
cache.put(key, false);
TypeDescriptor td = bw.getPropertyTypeDescriptor(prop);
if (td != null) {
WinletDefaultFormattingConversionService wcs = get();
if (wcs != null
&& wcs.hasFmtAnnotation(td)
&& wcs.canConvert(td,
TypeDescriptor.valueOf(String.class)))
cache.put(key, true);
}
}
return cache.get(key);
}
public static boolean canFormat(Object obj, String prop) {
return canFormat(new BeanWrapperImpl(obj), obj, prop);
}
/**
* 如果有格式可应用则应用
*
* @param bw
* @param obj
* @param prop
* @return
*/
public static String format(ConfigurablePropertyAccessor bw, Object obj,
String prop) {
String key = obj.getClass().getName() + "_" + prop;
if (!cache.containsKey(key))
canFormat(bw, obj, prop);
Object val = bw.getPropertyValue(prop);
if (val == null)
return null;
if (val.getClass().isArray())
return null;
if (!cache.get(key))
return val.toString();
TypeDescriptor td = bw.getPropertyTypeDescriptor(prop);
val = get().convert(val, td, TypeDescriptor.valueOf(String.class));
return val == null ? null : val.toString();
}
public static String format(Object obj, String prop) {
return format(new BeanWrapperImpl(obj), obj, prop);
}
}