protected Converter findInternalConverter()

in xbean-reflect/src/main/java/org/apache/xbean/propertyeditor/PropertyEditorRegistry.java [295:396]


    protected Converter findInternalConverter(final Type type) {
        if (type == null) {
            throw new NullPointerException("type is null");
        }

        final Class clazz = toClass(type);

        // it's possible this was a request for an array class.  We might not
        // recognize the array type directly, but the component type might be
        // resolvable
        if (clazz.isArray() && !clazz.getComponentType().isArray()) {
            // do a recursive lookup on the base type
            PropertyEditor editor = findConverter(clazz.getComponentType());
            // if we found a suitable editor for the base component type,
            // wrapper this in an array adaptor for real use
            if (editor != null) {
                return new ArrayConverter(clazz, editor);
            }
            return null;
        }

        if (Collection.class.isAssignableFrom(clazz)){
            Type[] types = getTypeParameters(Collection.class, type);

            Type componentType = String.class;
            if (types != null && types.length == 1 && types[0] instanceof Class) {
                componentType = types[0];
            }

            PropertyEditor editor = findConverter(componentType);

            if (editor != null){
                if (RecipeHelper.hasDefaultConstructor(clazz)) {
                    return new GenericCollectionConverter(clazz, editor);
                } else if (SortedSet.class.isAssignableFrom(clazz)) {
                    return new GenericCollectionConverter(TreeSet.class, editor);
                } else if (Set.class.isAssignableFrom(clazz)) {
                    return new GenericCollectionConverter(LinkedHashSet.class, editor);
                }
                return new GenericCollectionConverter(ArrayList.class, editor);
            }

            return null;
        }

        if (Map.class.isAssignableFrom(clazz)){
            Type[] types = getTypeParameters(Map.class, type);

            Type keyType = String.class;
            Type valueType = String.class;
            if (types != null && types.length == 2 && types[0] instanceof Class && types[1] instanceof Class) {
                keyType = types[0];
                valueType = types[1];
            }

            final Converter keyConverter = findConverter(keyType);
            final Converter valueConverter = findConverter(valueType);

            if (keyConverter != null && valueConverter != null){
                if (RecipeHelper.hasDefaultConstructor(clazz)) {
                    return new GenericMapConverter(clazz, keyConverter, valueConverter);
                } else if (SortedMap.class.isAssignableFrom(clazz)) {
                    return new GenericMapConverter(TreeMap.class, keyConverter, valueConverter);
                } else if (ConcurrentMap.class.isAssignableFrom(clazz)) {
                    return new GenericMapConverter(ConcurrentHashMap.class, keyConverter, valueConverter);
                }
                return new GenericMapConverter(LinkedHashMap.class, keyConverter, valueConverter);
            }

            return null;
        }

        Converter converter = registry.get(clazz);

        // we're outta here if we got one.
        if (converter != null) {
            return converter;
        }

        final Class[] declaredClasses = clazz.getDeclaredClasses();
        for (final Class<?> declaredClass : declaredClasses) {
            if (Converter.class.isAssignableFrom(declaredClass)) {
                try {
                    converter = (Converter) declaredClass.newInstance();
                    register(converter);

                    // try to get the converter from the registry... the converter
                    // created above may have been for another class
                    converter = registry.get(clazz);
                    if (converter != null) {
                        return converter;
                    }
                } catch (Exception e) {
                    // no-op
                }

            }
        }

        // nothing found
        return null;
    }