/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
* All rights reserved.
*
* 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 br.com.caelum.vraptor.http.ognl;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import net.vidageek.mirror.dsl.Mirror;
/**
* Capable of instantiating generic interfaces and custom types.
*
* @author Guilherme Silveira
*/
public class GenericNullHandler implements NullHandler {
private static final Map<Class<?>, Class<?>> CONCRETE_TYPES = new HashMap<Class<?>, Class<?>>();
private final EmptyElementsRemoval removal;
static {
CONCRETE_TYPES.put(List.class, ArrayList.class);
CONCRETE_TYPES.put(Calendar.class, GregorianCalendar.class);
CONCRETE_TYPES.put(Collection.class, ArrayList.class);
CONCRETE_TYPES.put(Set.class, HashSet.class);
CONCRETE_TYPES.put(SortedSet.class, TreeSet.class);
CONCRETE_TYPES.put(Queue.class, LinkedList.class);
}
public GenericNullHandler(EmptyElementsRemoval removal) {
this.removal = removal;
}
public <T> T instantiate(Class<T> baseType) {
if (baseType.isArray()) {
return baseType.cast(Array.newInstance(baseType.getComponentType(), 0));
}
Class<?> typeToInstantiate = baseType;
if (baseType.isInterface() || Modifier.isAbstract(baseType.getModifiers())) {
if (!CONCRETE_TYPES.containsKey(baseType)) {
// TODO better
throw new IllegalArgumentException("Vraptor does not support this interface or abstract type: "
+ typeToInstantiate.getName());
}
typeToInstantiate = CONCRETE_TYPES.get(baseType);
}
Object instance = new Mirror().on(typeToInstantiate).invoke().constructor().withoutArgs();
if(Collection.class.isAssignableFrom(typeToInstantiate)) {
removal.add((Collection)instance);
}
return baseType.cast(instance);
}
}