blob: d74bcca3298a8e8a7075b79f290faba1d95a9dd4 [file] [log] [blame]
/**
*
* Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xbean.recipe;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.xbean.ClassLoading;
/**
* @version $Rev: 6687 $ $Date: 2005-12-28T21:08:56.733437Z $
*/
public class MapRecipe implements Recipe {
private final List entries;
private final String type;
public MapRecipe() {
type = LinkedHashMap.class.getName();
entries = new ArrayList();
}
public MapRecipe(String type) {
this.type = type;
entries = new ArrayList();
}
public MapRecipe(Class type) {
this.type = type.getName();
if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
entries = new ArrayList();
}
public MapRecipe(Map map) {
if (map == null) throw new NullPointerException("map is null");
entries = new ArrayList(map.size());
// If the specified set has a default constructor we will recreate the set, otherwise we use a LinkedHashMap or TreeMap
if (RecipeHelper.hasDefaultConstructor(map.getClass())) {
this.type = map.getClass().getName();
} else if (map instanceof SortedMap) {
this.type = TreeMap.class.getName();
} else {
this.type = LinkedHashMap.class.getName();
}
putAll(map);
}
public MapRecipe(String type, Map map) {
if (map == null) throw new NullPointerException("map is null");
this.type = type;
entries = new ArrayList(map.size());
putAll(map);
}
public MapRecipe(Class type, Map map) {
if (map == null) throw new NullPointerException("map is null");
if (!RecipeHelper.hasDefaultConstructor(type)) throw new IllegalArgumentException("Type does not have a default constructor " + type);
this.type = type.getName();
entries = new ArrayList(map.size());
putAll(map);
}
public MapRecipe(MapRecipe mapRecipe) {
if (mapRecipe == null) throw new NullPointerException("mapRecipe is null");
this.type = mapRecipe.type;
entries = new ArrayList(mapRecipe.entries);
}
public Object create(ClassLoader classLoader) {
Class mapType = null;
try {
mapType = ClassLoading.loadClass(type, classLoader);
} catch (ClassNotFoundException e) {
throw new ConstructionException("Type class could not be found: " + type);
}
if (!RecipeHelper.hasDefaultConstructor(mapType)) {
throw new ConstructionException("Type does not have a default constructor " + type);
}
Object o;
try {
o = mapType.newInstance();
} catch (Exception e) {
throw new ConstructionException("Error while creating set instance: " + type);
}
if(!(o instanceof Map)) {
throw new ConstructionException("Specified map type does not implement the Map interface: " + type);
}
Map instance = (Map) o;
for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
Object[] entry = (Object[]) iterator.next();
Object key = entry[0];
if (key instanceof Recipe) {
Recipe recipe = (Recipe) key;
try {
key = recipe.create(classLoader);
} catch (ConstructionException e) {
e.setPrependAttributeName("[" + type + " " + key + "]");
throw e;
}
}
Object value = entry[1];
if (value instanceof Recipe) {
Recipe recipe = (Recipe) value;
try {
value = recipe.create(classLoader);
} catch (ConstructionException e) {
e.setPrependAttributeName("[" + type + " " + key + "]");
throw e;
}
}
instance.put(key, value);
}
return instance;
}
public void put(Object key, Object value) {
if (key == null) throw new NullPointerException("key is null");
if (!RecipeHelper.isSimpleType(key)) {
key = new ValueRecipe(key);
}
if (!RecipeHelper.isSimpleType(value)) {
value = new ValueRecipe(value);
}
entries.add(new Object[] { key, value});
}
public void putAll(Map map) {
if (map == null) throw new NullPointerException("map is null");
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
put(key, value);
}
}
}