package flexjson;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class BeanAnalyzer
{
private static ThreadLocal<Map<Class, BeanAnalyzer>> cache= new ThreadLocal<Map<Class, BeanAnalyzer>>();
private Class clazz2;
private BeanAnalyzer superBean;
private Map<String, BeanProperty> properties;
public static BeanAnalyzer analyze(Class clazz2)
{
if (cache.get() == null)
cache.set(new HashMap<Class, BeanAnalyzer>());
if (clazz2 == null)
return null;
if (!cache.get().containsKey(clazz2))
{
cache.get().put(clazz2, new BeanAnalyzer(clazz2));
}
return cache.get().get(clazz2);
}
public static void clearCache()
{
cache.remove();
}
protected BeanAnalyzer(Class clazz)
{
this.clazz2= clazz;
superBean= analyze(clazz.getSuperclass());
populateProperties();
}
private void populateProperties()
{
properties= new HashMap<String, BeanProperty>();
for (Method method : clazz2.getDeclaredMethods())
{
int modifiers= method.getModifiers();
if (Modifier.isStatic(modifiers))
continue;
int numberOfArgs= method.getParameterTypes().length;
String name= method.getName();
if (name.length() <= 3 && !name.startsWith("is"))
continue;
if (numberOfArgs == 0)
{
if (name.startsWith("get"))
{
String property= uncapitalize(name.substring(3));
if (!properties.containsKey(property))
{
properties.put(property, new BeanProperty(property, this));
}
properties.get(property).setReadMethod(method);
}
else if (name.startsWith("is"))
{
String property= uncapitalize(name.substring(2));
if (!properties.containsKey(property))
{
properties.put(property, new BeanProperty(property, this));
}
properties.get(property).setReadMethod(method);
}
}
else if (numberOfArgs == 1)
{
if (name.startsWith("set"))
{
String property= uncapitalize(name.substring(3));
if (!properties.containsKey(property))
{
properties.put(property, new BeanProperty(property, this));
}
properties.get(property).addWriteMethod(method);
}
}
}
for (Field publicProperties : clazz2.getFields())
{
int modifiers= publicProperties.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))
continue;
if (!properties.containsKey(publicProperties.getName()))
{
properties.put(publicProperties.getName(), new BeanProperty(publicProperties, this));
}
}
}
public BeanAnalyzer getSuperBean()
{
return superBean;
}
private String uncapitalize(String value)
{
if (value.length() < 2)
{
return value.toLowerCase();
}
else if (Character.isUpperCase(value.charAt(0)) && Character.isUpperCase(value.charAt(1)))
{
return value;
}
else
{
return Character.toLowerCase(value.charAt(0)) + value.substring(1);
}
}
public BeanProperty getProperty(String name)
{
BeanAnalyzer current= this;
while (current != null)
{
BeanProperty property= current.properties.get(name);
if (property != null)
return property;
current= current.superBean;
}
return null;
}
public Collection<BeanProperty> getProperties()
{
Map<String, BeanProperty> properties= new HashMap<String, BeanProperty>(this.properties);
BeanAnalyzer current= this.superBean;
while (current != null)
{
merge(properties, current.properties);
current= current.superBean;
}
return properties.values();
}
private void merge(Map<String, BeanProperty> destination, Map<String, BeanProperty> source)
{
for (String key : source.keySet())
{
if (!destination.containsKey(key))
{
destination.put(key, source.get(key));
}
}
}
public boolean hasProperty(String name)
{
return properties.containsKey(name);
}
protected Field getDeclaredField(String name)
{
try
{
return clazz2.getDeclaredField(name);
}
catch (NoSuchFieldException e)
{
// ignore field does not exist.
return null;
}
}
}