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 java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Iterator;
022    import java.util.LinkedHashSet;
023    import java.util.List;
024    import java.util.Set;
025    import java.util.SortedSet;
026    import java.util.TreeSet;
027    
028    /**
029     * @version $Rev: 6685 $ $Date: 2005-12-28T00:29:37.967210Z $
030     */
031    public class CollectionRecipe extends AbstractRecipe {
032        private final List<Object> list;
033        private final String type;
034    
035        public CollectionRecipe() {
036            list = new ArrayList<Object>();
037            type = ArrayList.class.getName();
038        }
039    
040        public CollectionRecipe(String type) {
041            list = new ArrayList<Object>();
042            this.type = type;
043        }
044    
045        public CollectionRecipe(Class type) {
046            if (type == null) throw new NullPointerException("type is null");
047            if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
048            this.list = new ArrayList<Object>();
049            this.type = type.getName();
050        }
051    
052        public CollectionRecipe(Collection collection) {
053            if (collection == null) throw new NullPointerException("collection is null");
054    
055            this.list = new ArrayList<Object>(collection.size());
056    
057            // If the specified set has a default constructor we will recreate the set, otherwise we use a the default
058            if (RecipeHelper.hasDefaultConstructor(collection.getClass())) {
059                this.type = collection.getClass().getName();
060            } else if (collection instanceof SortedSet) {
061                this.type = TreeSet.class.getName();
062            } else if (collection instanceof Set) {
063                this.type = LinkedHashSet.class.getName();
064            } else {
065                this.type = ArrayList.class.getName();
066            }
067            addAll(collection);
068        }
069    
070        public CollectionRecipe(String type, Collection collection) {
071            if (type == null) throw new NullPointerException("type is null");
072            if (collection == null) throw new NullPointerException("collection is null");
073            this.list = new ArrayList<Object>(collection.size());
074            this.type = type;
075            addAll(collection);
076        }
077    
078        public CollectionRecipe(Class type, Collection collection) {
079            if (type == null) throw new NullPointerException("type is null");
080            if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
081            if (collection == null) throw new NullPointerException("collection is null");
082            this.list = new ArrayList<Object>(collection.size());
083            this.type = type.getName();
084            addAll(collection);
085        }
086    
087        public CollectionRecipe(CollectionRecipe collectionRecipe) {
088            if (collectionRecipe == null) throw new NullPointerException("setRecipe is null");
089            this.type = collectionRecipe.type;
090            list = new ArrayList<Object>(collectionRecipe.list);
091        }
092    
093        public boolean canCreate(Class type, ClassLoader classLoader) {
094            Class myType = getType(classLoader);
095            return type.isAssignableFrom(myType);
096        }
097    
098        public Collection create(ClassLoader classLoader) {
099            Class setType = getType(classLoader);
100    
101            if (!RecipeHelper.hasDefaultConstructor(setType)) {
102                throw new ConstructionException("Type does not have a default constructor " + type);
103            }
104    
105            Object o;
106            try {
107                o = setType.newInstance();
108            } catch (Exception e) {
109                throw new ConstructionException("Error while creating set instance: " + type);
110            }
111    
112            if(!(o instanceof Collection)) {
113                throw new ConstructionException("Specified set type does not implement the Collection interface: " + type);
114            }
115    
116            Collection instance = (Collection) o;
117            int i =0;
118            for (Iterator iterator = list.iterator(); iterator.hasNext();) {
119                Object value = iterator.next();
120                if (value instanceof Recipe) {
121                    Recipe recipe = (Recipe) value;
122                    try {
123                        value = recipe.create(classLoader);
124                    } catch (ConstructionException e) {
125                        e.setPrependAttributeName("[" + type + " item " + i + "]");
126                        throw e;
127                    }
128                }
129                //noinspection unchecked
130                instance.add(value);
131                i++;
132            }
133            return instance;
134        }
135    
136        private Class getType(ClassLoader classLoader) {
137            Class setType = null;
138            try {
139                setType = Class.forName(type, true, classLoader);
140            } catch (ClassNotFoundException e) {
141                throw new ConstructionException("Type class could not be found: " + type);
142            }
143            return setType;
144        }
145    
146        public void add(Boolean value) {
147            if (value == null) throw new NullPointerException("value is null");
148            list.add(value);
149        }
150    
151        public void add(Character value) {
152            if (value == null) throw new NullPointerException("value is null");
153            list.add(value);
154        }
155    
156        public void add(Byte value) {
157            if (value == null) throw new NullPointerException("value is null");
158            list.add(value);
159        }
160    
161        public void add(Short value) {
162            if (value == null) throw new NullPointerException("value is null");
163            list.add(value);
164        }
165    
166        public void add(Integer value) {
167            if (value == null) throw new NullPointerException("value is null");
168            list.add(value);
169        }
170    
171        public void add(Long value) {
172            if (value == null) throw new NullPointerException("value is null");
173            list.add(value);
174        }
175    
176        public void add(Float value) {
177            if (value == null) throw new NullPointerException("value is null");
178            list.add(value);
179        }
180    
181        public void add(Double value) {
182            if (value == null) throw new NullPointerException("value is null");
183            list.add(value);
184        }
185    
186        public void add(String value) {
187            if (value == null) throw new NullPointerException("value is null");
188            list.add(value);
189        }
190    
191        public void add(Recipe value) {
192            if (value == null) throw new NullPointerException("value is null");
193            list.add(value);
194        }
195    
196        public void addAll(Collection value) {
197            if (value == null) throw new NullPointerException("value is null");
198            for (Iterator iterator = value.iterator(); iterator.hasNext();) {
199                Object o = iterator.next();
200                if (o instanceof Boolean) {
201                    add((Boolean)o);
202                } else if (o instanceof Character) {
203                    add((Character)o);
204                } else if (o instanceof Byte) {
205                    add((Byte)o);
206                } else if (o instanceof Short) {
207                    add((Short)o);
208                } else if (o instanceof Integer) {
209                    add((Integer)o);
210                } else if (o instanceof Long) {
211                    add((Long)o);
212                } else if (o instanceof Float) {
213                    add((Float)o);
214                } else if (o instanceof Double) {
215                    add((Double)o);
216                } else if (o instanceof String) {
217                    add((String)o);
218                } else if (o instanceof Recipe) {
219                    add((Recipe)o);
220                } else {
221                    add(new ValueRecipe(o));
222                }
223            }
224        }
225    
226    }