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 + -
显示快捷键?