001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.xbean.recipe;
018    
019    import org.apache.xbean.propertyeditor.PropertyEditors;
020    
021    import java.lang.reflect.Modifier;
022    import java.lang.reflect.Constructor;
023    import java.util.Comparator;
024    import java.util.Map;
025    import java.util.List;
026    import java.util.Collections;
027    import java.util.ArrayList;
028    
029    /**
030     * @version $Rev: 6687 $ $Date: 2005-12-28T21:08:56.733437Z $
031     */
032    public final class RecipeHelper {
033        private RecipeHelper() {
034        }
035    
036        public static boolean hasDefaultConstructor(Class type) {
037            if (!Modifier.isPublic(type.getModifiers())) {
038                return false;
039            }
040            Constructor[] constructors = type.getConstructors();
041            for (int i = 0; i < constructors.length; i++) {
042                Constructor constructor = constructors[i];
043                if (Modifier.isPublic(constructor.getModifiers()) &&
044                        constructor.getParameterTypes().length == 0) {
045                    return true;
046                }
047            }
048            return false;
049        }
050    
051        public static boolean isSimpleType(Object o) {
052            return  o == null ||
053                    o instanceof Boolean ||
054                    o instanceof Character ||
055                    o instanceof Byte ||
056                    o instanceof Short ||
057                    o instanceof Integer ||
058                    o instanceof Long ||
059                    o instanceof Float ||
060                    o instanceof Double ||
061                    o instanceof String ||
062                    o instanceof Recipe;
063    
064        }
065    
066        public static <K,V> List<Map.Entry<K,V>> prioritizeProperties(Map<K,V> properties) {
067            ArrayList<Map.Entry<K,V>> entries = new ArrayList<Map.Entry<K,V>>(properties.entrySet());
068            Collections.sort(entries, new RecipeComparator());
069            return entries;
070        }
071    
072        public static boolean isInstance(Class type, Object instance) {
073            if (type.isPrimitive()) {
074                // for primitives the insance can't be null
075                if (instance == null) {
076                    return false;
077                }
078    
079                // verify instance is the correct wrapper type
080                if (type.equals(boolean.class)) {
081                    return instance instanceof Boolean;
082                } else if (type.equals(char.class)) {
083                    return instance instanceof Character;
084                } else if (type.equals(byte.class)) {
085                    return instance instanceof Byte;
086                } else if (type.equals(short.class)) {
087                    return instance instanceof Short;
088                } else if (type.equals(int.class)) {
089                    return instance instanceof Integer;
090                } else if (type.equals(long.class)) {
091                    return instance instanceof Long;
092                } else if (type.equals(float.class)) {
093                    return instance instanceof Float;
094                } else if (type.equals(double.class)) {
095                    return instance instanceof Double;
096                } else {
097                    throw new AssertionError("Invalid primitve type: " + type);
098                }
099            }
100    
101            return instance == null || type.isInstance(instance);
102        }
103    
104        public static boolean isConvertable(Class type, Object propertyValue, ClassLoader classLoader) {
105            if (propertyValue instanceof Recipe) {
106                Recipe recipe = (Recipe) propertyValue;
107                return recipe.canCreate(type, classLoader);
108            }
109            return (propertyValue instanceof String && PropertyEditors.canConvert(type));
110        }
111    
112        public static boolean isAssignableFrom(Class expected, Class actual) {
113            if (expected.isPrimitive()) {
114                // verify actual is the correct wrapper type
115                if (expected.equals(boolean.class)) {
116                    return actual.equals(Boolean.class);
117                } else if (expected.equals(char.class)) {
118                    return actual.equals(Character.class);
119                } else if (expected.equals(byte.class)) {
120                    return actual.equals(Byte.class);
121                } else if (expected.equals(short.class)) {
122                    return actual.equals(Short.class);
123                } else if (expected.equals(int.class)) {
124                    return actual.equals(Integer.class);
125                } else if (expected.equals(long.class)) {
126                    return actual.equals(Long.class);
127                } else if (expected.equals(float.class)) {
128                    return actual.equals(Float.class);
129                } else if (expected.equals(double.class)) {
130                    return actual.equals(Double.class);
131                } else {
132                    throw new AssertionError("Invalid primitve type: " + expected);
133                }
134            }
135    
136            return expected.isAssignableFrom(actual);
137        }
138    
139        public static class RecipeComparator implements Comparator<Object> {
140            public int compare(Object left, Object right) {
141                if (!(left instanceof Recipe) && !(right instanceof Recipe)) return 0;
142                if (left instanceof Recipe && !(right instanceof Recipe)) return 1;
143                if (!(left instanceof Recipe) && right instanceof Recipe) return -1;
144    
145                float leftPriority = ((Recipe) left).getPriority();
146                float rightPriority = ((Recipe) right).getPriority();
147    
148                if (leftPriority > rightPriority) return 1;
149                if (leftPriority < rightPriority) return -1;
150                return 0;
151            }
152        }
153    }