public static List findAllFieldsByType()

in xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java [407:486]


    public static List<Field> findAllFieldsByType(Class typeClass, Object propertyValue, Set<Option> options,
                                                  PropertyEditorRegistry registry) {
        if (typeClass == null) throw new NullPointerException("typeClass is null");
        if (options == null) options = EnumSet.noneOf(Option.class);

        int matchLevel = 0;
        MissingAccessorException missException = null;

        List<Field> fields = new ArrayList<Field>(Arrays.asList(typeClass.getDeclaredFields()));
        Class parent = typeClass.getSuperclass();
        while (parent != null){
            fields.addAll(Arrays.asList(parent.getDeclaredFields()));
            parent = parent.getSuperclass();
        }

        boolean allowPrivate = options.contains(Option.PRIVATE_PROPERTIES);
        boolean allowStatic = options.contains(Option.STATIC_PROPERTIES);

        LinkedList<Field> validFields = new LinkedList<Field>();
        for (Field field : fields) {
            Class fieldType = field.getType();
            if (RecipeHelper.isInstance(fieldType, propertyValue) || RecipeHelper.isConvertable(fieldType, propertyValue, registry)) {
                if (!allowPrivate && !Modifier.isPublic(field.getModifiers())) {
                    if (matchLevel < 4) {
                        matchLevel = 4;
                        missException = new MissingAccessorException("Field is not public: " + field, matchLevel);
                    }
                    continue;
                }

                if (!allowStatic && Modifier.isStatic(field.getModifiers())) {
                    if (matchLevel < 4) {
                        matchLevel = 4;
                        missException = new MissingAccessorException("Field is static: " + field, matchLevel);
                    }
                    continue;
                }


                if (fieldType.isPrimitive() && propertyValue == null) {
                    if (matchLevel < 6) {
                        matchLevel = 6;
                        missException = new MissingAccessorException("Null can not be assigned to " +
                                fieldType.getName() + ": " + field, matchLevel);
                    }
                    continue;
                }

                if (allowPrivate && !Modifier.isPublic(field.getModifiers())) {
                    setAccessible(field);
                }

                if (RecipeHelper.isInstance(fieldType, propertyValue)) {
                    // This field requires no conversion, which means there can not be a conversion error.
                    // Therefore this setter is perferred and put a the head of the list
                    validFields.addFirst(field);
                } else {
                    validFields.add(field);
                }
            }
        }

        if (!validFields.isEmpty()) {
            // remove duplicate methods (can happen with inheritance)
            return new ArrayList<Field>(new LinkedHashSet<Field>(validFields));
        }

        if (missException != null) {
            throw missException;
        } else {
            StringBuffer buffer = new StringBuffer("Unable to find a valid field ");
            if (propertyValue instanceof Recipe) {
                buffer.append("for ").append(propertyValue == null ? "null" : propertyValue);
            } else {
                buffer.append("of type ").append(propertyValue == null ? "null" : propertyValue.getClass().getName());
            }
            buffer.append(" in class ").append(typeClass.getName());
            throw new MissingAccessorException(buffer.toString(), -1);
        }
    }