001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.mina.integration.beans;
021
022import java.beans.PropertyEditor;
023import java.util.Collection;
024import java.util.List;
025import java.util.Map;
026import java.util.Properties;
027import java.util.Set;
028
029/**
030 * A factory that creates a new {@link PropertyEditor} which is appropriate for
031 * the specified object or class. 
032 * 
033 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
034 */
035public final class PropertyEditorFactory {
036    @SuppressWarnings("unchecked")
037    public static PropertyEditor getInstance(Object object) {
038        if (object == null) {
039            return new NullEditor();
040        }
041
042        if (object instanceof Collection<?>) {
043            Class<?> elementType = null;
044            
045            for (Object e : (Collection<Object>) object) {
046                if (e != null) {
047                    elementType = e.getClass();
048                    break;
049                }
050            }
051
052            if (elementType != null) {
053                if (object instanceof Set) {
054                    return new SetEditor(elementType);
055                }
056
057                if (object instanceof List) {
058                    return new ListEditor(elementType);
059                }
060
061                return new CollectionEditor(elementType);
062            }
063        }
064
065        if (object instanceof Map) {
066            Class<?> keyType = null;
067            Class<?> valueType = null;
068            
069            for (Object entry : ((Map<?,?>) object).entrySet()) {
070                Map.Entry<?,?> e = (Map.Entry<?,?>) entry;
071                
072                if ((e.getKey() != null) && (e.getValue() != null)) {
073                    keyType = e.getKey().getClass();
074                    valueType = e.getValue().getClass();
075                    break;
076                }
077            }
078
079            if ((keyType != null) && (valueType != null)) {
080                return new MapEditor(keyType, valueType);
081            }
082        }
083
084        return getInstance(object.getClass());
085    }
086
087    // parent type / property name / property type
088    public static PropertyEditor getInstance(Class<?> type) {
089        if (type == null) {
090            throw new IllegalArgumentException("type");
091        }
092
093        if (type.isEnum()) {
094            return new EnumEditor(type);
095        }
096
097        if (type.isArray()) {
098            return new ArrayEditor(type.getComponentType());
099        }
100
101        if (Collection.class.isAssignableFrom(type)) {
102            if (Set.class.isAssignableFrom(type)) {
103                return new SetEditor(String.class);
104            }
105
106            if (List.class.isAssignableFrom(type)) {
107                return new ListEditor(String.class);
108            }
109
110            return new CollectionEditor(String.class);
111        }
112
113        if (Map.class.isAssignableFrom(type)) {
114            return new MapEditor(String.class, String.class);
115        }
116
117        if (Properties.class.isAssignableFrom(type)) {
118            return new PropertiesEditor();
119        }
120
121        type = filterPrimitiveType(type);
122
123        try {
124            return (PropertyEditor) PropertyEditorFactory.class
125                    .getClassLoader()
126                    .loadClass(
127                            PropertyEditorFactory.class.getPackage().getName() + '.' + type.getSimpleName() + "Editor")
128                    .newInstance();
129        } catch (Exception e) {
130            return null;
131        }
132    }
133
134    private static Class<?> filterPrimitiveType(Class<?> type) {
135        if (type.isPrimitive()) {
136            if (type == boolean.class) {
137                type = Boolean.class;
138            }
139            if (type == byte.class) {
140                type = Byte.class;
141            }
142            if (type == char.class) {
143                type = Character.class;
144            }
145            if (type == double.class) {
146                type = Double.class;
147            }
148            if (type == float.class) {
149                type = Float.class;
150            }
151            if (type == int.class) {
152                type = Integer.class;
153            }
154            if (type == long.class) {
155                type = Long.class;
156            }
157            if (type == short.class) {
158                type = Short.class;
159            }
160        }
161        return type;
162    }
163
164    private PropertyEditorFactory() {
165    }
166}