metaclassimpl.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,511 行 · 第 1/5 页
JAVA
1,511 行
List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods(sender, name);
if (possibleGenericMethods != null) {
for (Iterator iter = possibleGenericMethods.iterator(); iter.hasNext();) {
MetaMethod mmethod = (MetaMethod) iter.next();
Class[] paramTypes = mmethod.getParameterTypes();
if (useLongVersion) {
if (paramTypes.length==2 && paramTypes[0] == String.class) {
return mmethod;
}
} else {
if (paramTypes.length==1) return mmethod;
}
}
}
return null;
}
/**
* Get all the properties defined for this type
* @return a list of MetaProperty objects
*/
public List getProperties() {
checkInitalised();
Map propertyMap = (Map) classPropertyIndex.get(theClass);
// simply return the values of the metaproperty map as a List
List ret = new ArrayList(propertyMap.size());
for (Iterator iter = propertyMap.values().iterator(); iter.hasNext();) {
MetaProperty element = (MetaProperty) iter.next();
if (element instanceof MetaFieldProperty) continue;
// filter out DGM beans
if (element instanceof MetaBeanProperty) {
MetaBeanProperty mp = (MetaBeanProperty) element;
boolean setter = true;
boolean getter = true;
if (mp.getGetter()==null || mp.getGetter() instanceof NewInstanceMetaMethod) {
getter=false;
}
if (mp.getSetter()==null || mp.getSetter() instanceof NewInstanceMetaMethod) {
setter=false;
}
if (!setter && !getter) continue;
if (!setter && mp.getSetter()!=null) {
element = new MetaBeanProperty(mp.getName(),mp.getType(),mp.getGetter(),null);
}
if (!getter && mp.getGetter()!=null) {
element = new MetaBeanProperty(mp.getName(),mp.getType(), null, mp.getSetter());
}
}
ret.add(element);
}
return ret;
}
private MetaMethod findPropertyMethod(List methods, boolean isGetter) {
LinkedList ret = new LinkedList();
for (Iterator iter = methods.iterator(); iter.hasNext();) {
MetaMethod element = (MetaMethod) iter.next();
if ( !isGetter &&
//(element.getReturnType() == Void.class || element.getReturnType() == Void.TYPE) &&
element.getParameterTypes().length == 1)
{
ret.add(element);
}
if ( isGetter &&
!(element.getReturnType() == Void.class || element.getReturnType() == Void.TYPE) &&
element.getParameterTypes().length == 0)
{
ret.add(element);
}
}
if (ret.size() == 0) return null;
if (ret.size() == 1) return (MetaMethod) ret.getFirst();
// we found multiple matching methods
// this is a problem, because we can use only one
// if it is a getter, then use the most general return
// type to decide which method to use. If it is a setter
// we use the type of the first parameter
MetaMethod method = null;
int distance = -1;
for (Iterator iter = ret.iterator(); iter.hasNext();) {
MetaMethod element = (MetaMethod) iter.next();
Class c;
if (isGetter) {
c = element.getReturnType();
} else {
c = element.getParameterTypes()[0];
}
int localDistance = distanceToObject(c);
//TODO: maybe implement the case localDistance==distance
if (distance==-1 || distance>localDistance) {
distance = localDistance;
method = element;
}
}
return method;
}
private static int distanceToObject(Class c) {
int count;
for (count=0; c!=null; count++) {
c=c.getSuperclass();
}
return count;
}
/**
* This will build up the property map (Map of MetaProperty objects, keyed on
* property name).
*/
private void setupProperties(PropertyDescriptor[] propertyDescriptors) {
LinkedList superClasses = getSuperClasses();
Set interfaces = new HashSet();
makeInterfaceSet(theClass,interfaces);
// if this an Array, then add the special read-only "length" property
if (theClass.isArray()) {
Map map = new HashMap();
map.put("length", arrayLengthProperty);
classPropertyIndex.put(theClass,map);
}
inheritStaticInterfaceFields(superClasses, interfaces);
inheritFields(superClasses);
applyPropertyDescriptors(propertyDescriptors);
applyStrayPropertyMethods(superClasses,classMethodIndex,classPropertyIndex);
applyStrayPropertyMethods(superClasses,classMethodIndexForSuper,classPropertyIndexForSuper);
copyClassPropertyIndexForSuper();
makeStaticPropertyIndex();
}
private void makeStaticPropertyIndex() {
Map propertyMap = (Map) classPropertyIndex.get(theClass);
for (Iterator iter = propertyMap.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
MetaProperty mp = (MetaProperty) entry.getValue();
if (mp instanceof MetaFieldProperty) {
MetaFieldProperty mfp = (MetaFieldProperty) mp;
if (!mfp.isStatic()) continue;
} else if (mp instanceof MetaBeanProperty) {
MetaBeanProperty mbp = (MetaBeanProperty) mp;
boolean getter = mbp.getGetter()==null || mbp.getGetter().isStatic();
boolean setter = mbp.getSetter()==null || mbp.getSetter().isStatic();
boolean field = mbp.getField()==null || mbp.getField().isStatic();
if (!getter && !setter && !field) {
continue;
} else if (setter && getter) {
if (field) {
mp = mbp; // nothing to do
} else {
mp = new MetaBeanProperty(mbp.getName(),mbp.getType(),mbp.getGetter(),mbp.getSetter());
}
} else if (getter && !setter) {
if (mbp.getGetter()==null) {
mp = mbp.getField();
} else {
MetaBeanProperty newmp = new MetaBeanProperty(mbp.getName(),mbp.getType(),mbp.getGetter(),null);
if (field) newmp.setField(mbp.getField());
mp = newmp;
}
} else if (setter && !getter) {
if (mbp.getSetter()==null) {
mp = mbp.getField();
} else {
MetaBeanProperty newmp = new MetaBeanProperty(mbp.getName(),mbp.getType(),null,mbp.getSetter());
if (field) newmp.setField(mbp.getField());
mp = newmp;
}
} else if (field) {
mp = mbp.getField();
}
} else {
continue; // ignore all other types
}
if (mp==null) continue;
staticPropertyIndex.put(entry.getKey(),mp);
}
}
private void copyClassPropertyIndexForSuper() {
for (Iterator iter = classPropertyIndex.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
HashMap newVal = new HashMap((Map)entry.getValue());
classPropertyIndexForSuper.put(entry.getKey(),newVal);
}
}
private Map getMap2MapNotNull(Map m, Object key) {
Map ret = (Map) m.get(key);
if (ret==null) {
ret = new HashMap();
m.put(key,ret);
}
return ret;
}
private void inheritStaticInterfaceFields(LinkedList superClasses, Set interfaces) {
for (Iterator interfaceIter = interfaces.iterator(); interfaceIter.hasNext();) {
Class iclass = (Class) interfaceIter.next();
Map iPropertyIndex = getMap2MapNotNull(classPropertyIndex,iclass);
addFields(iclass,iPropertyIndex);
for (Iterator classIter = superClasses.iterator(); classIter.hasNext();) {
Class sclass = (Class) classIter.next();
if (! iclass.isAssignableFrom(sclass)) continue;
Map sPropertyIndex = getMap2MapNotNull(classPropertyIndex,sclass);
copyNonPrivateFields(iPropertyIndex,sPropertyIndex);
}
}
}
private void inheritFields(LinkedList superClasses) {
Map last = null;
for (Iterator iter = superClasses.iterator(); iter.hasNext();) {
Class klass = (Class) iter.next();
Map propertyIndex = getMap2MapNotNull(classPropertyIndex,klass);
if (last != null) {
copyNonPrivateFields(last,propertyIndex);
}
last = propertyIndex;
addFields(klass,propertyIndex);
}
}
private void addFields(final Class klass, Map propertyIndex) {
Field[] fields = (Field[]) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return klass.getDeclaredFields();
}
});
for(int i = 0; i < fields.length; i++) {
MetaFieldProperty mfp = new MetaFieldProperty(fields[i]);
propertyIndex.put(fields[i].getName(), mfp);
}
}
private void copyNonPrivateFields(Map from, Map to) {
for (Iterator iter = from.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
MetaFieldProperty mfp = (MetaFieldProperty) entry.getValue();
if (!Modifier.isPublic(mfp.getModifiers()) && !Modifier.isProtected(mfp.getModifiers())) continue;
to.put(entry.getKey(),mfp);
}
}
private void applyStrayPropertyMethods(LinkedList superClasses, Map classMethodIndex, Map classPropertyIndex) {
// now look for any stray getters that may be used to define a property
for (Iterator iter = superClasses.iterator(); iter.hasNext();) {
Class klass = (Class) iter.next();
Map methodIndex = (Map) classMethodIndex.get(klass);
Map propertyIndex = getMap2MapNotNull(classPropertyIndex,klass);
for (Iterator nameMethodIterator = methodIndex.entrySet().iterator(); nameMethodIterator.hasNext();) {
Map.Entry entry = (Map.Entry) nameMethodIterator.next();
String methodName = (String) entry.getKey();
// name too sort?
if (methodName.length() < 4) continue;
//possible getter/setter
boolean isGetter = methodName.startsWith("get");
boolean isSetter = methodName.startsWith("set");
if (!isGetter && !isSetter) continue;
// get the name of the property
String propName = methodName.substring(3,4).toLowerCase() + methodName.substring(4);
MetaMethod propertyMethod = findPropertyMethod((List) entry.getValue(), isGetter);
if (propertyMethod==null) continue;
createMetaBeanProperty(propertyIndex, propName, isGetter, propertyMethod);
}
}
}
private void createMetaBeanProperty(Map propertyIndex, String propName, boolean isGetter, MetaMethod propertyMethod){
// is this property already accounted for?
MetaProperty mp = (MetaProperty) propertyIndex.get(propName);
if (mp == null) {
if (isGetter) {
mp = new MetaBeanProperty(propName,
propertyMethod.getReturnType(),
propertyMethod, null);
} else {
//isSetter
mp = new MetaBeanProperty(propName,
propertyMethod.getParameterTypes()[0],
null, propertyMethod);
}
} else {
MetaBeanProperty mbp;
MetaFieldProperty mfp;
if (mp instanceof MetaBeanProperty) {
mbp = (MetaBeanProperty) mp;
mfp = mbp.getField();
} else if (mp instanceof MetaFieldProperty){
mfp = (MetaFieldProperty) mp;
mbp = new MetaBeanProperty(propName,
mfp.getType(),
null, null);
} else {
throw new GroovyBugError("unknown MetaProperty class used. Class is "+mp.getClass());
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?