/*
* Grapht, an open source dependency injector.
* Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
* Copyright 2010-2014 Regents of the University of Minnesota
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* Helper methods for instantiate() method
* ClassInstantiator
*
* @author <a href="http://grouplens.org">GroupLens Research</a>
*/
package org.grouplens.grapht.reflect.internal;
import org.grouplens.grapht.ConstructionException;
import org.grouplens.grapht.Instantiator;
import org.grouplens.grapht.reflect.InjectionPoint;
import org.grouplens.grapht.util.LogContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
enum InjectionStrategy {
// method invoked for Field-Injection type
FIELD {
@Override
public void inject(InjectionPoint ip, Object instance, Instantiator provider,
Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
throws ConstructionException {
Field field;
Object value;
FieldInjectionPoint fd = (FieldInjectionPoint)ip;
try {
value = ClassInstantiator.checkNull(fd, provider.instantiate());
field = fd.getMember();
logger.trace("Setting field {} with arguments {}", field, value);
field.setAccessible(true);
field.set(instance, value);
} catch (IllegalAccessException e) {
throw new ConstructionException(fd, e);
}
}
},
// method invoked for Setter-Injection type
SETTER {
@Override
public void inject(InjectionPoint ip, Object instance, Instantiator provider,
Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
throws ConstructionException {
SetterInjectionPoint st = (SetterInjectionPoint)ip;
ClassInstantiator.InjectionArgs args = settersAndArguments.get(st.getMember());
Method setter = st.getMember();
if (args == null) {
//first encounter of this method
args = new ClassInstantiator.InjectionArgs(setter.getParameterTypes().length);
settersAndArguments.put(setter, args);
}
args.set(st.getParameterIndex(), ClassInstantiator.checkNull(st, provider.instantiate()));
if (args.isCompleted()) {
// all parameters initialized, invoke the setter with all arguments
try {
logger.trace("Invoking setter {} with arguments {}", setter, args.arguments);
setter.setAccessible(true);
setter.invoke(instance, args.arguments);
} catch (InvocationTargetException e) {
String message = "Exception thrown by ";
if (args.arguments.length == 1) {
message += st;
} else {
message += setter;
}
throw new ConstructionException(st, message, e);
} catch (IllegalAccessException e) {
String message = "Access violation calling ";
if (args.arguments.length == 1) {
message += st;
} else {
message += setter;
}
throw new ConstructionException(st, message, e);
}
}
}
},
// method invoked for NoArgument-Injection type.
NOARGUMENT {
@Override
public void inject(InjectionPoint ip, Object instance, Instantiator provider,
Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
throws ConstructionException {
Method method = null;
NoArgumentInjectionPoint noArugment = (NoArgumentInjectionPoint)ip;
try {
method = noArugment.getMember();
logger.trace("Injection point method with no argument in progress {}",noArugment);
logger.trace("Invoking no-argument injection point {}", ip);
method.setAccessible(true);
method.invoke(instance);
} catch (InvocationTargetException e) {
throw new ConstructionException(ip, "Exception throw by " + method, e);
} catch (IllegalAccessException e) {
throw new ConstructionException(ip, "Access violation invoking " + method, e);
}
}
},
DEFAULTCASE {
@Override
public void inject(InjectionPoint ip, Object instance, Instantiator provider,
Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
throws ConstructionException {
}
};
private static final Logger logger = LoggerFactory.getLogger(InjectionStrategy.class);
public abstract void inject(InjectionPoint ip, Object instance, Instantiator provider,
Map<Method, ClassInstantiator.InjectionArgs> settersAndArguments)
throws ConstructionException;
public static InjectionStrategy forInjectionPoint(InjectionPoint ip) {
if(ip instanceof FieldInjectionPoint) {
return InjectionStrategy.FIELD;
}
else if(ip instanceof SetterInjectionPoint) {
return InjectionStrategy.SETTER;
}
else if(ip instanceof NoArgumentInjectionPoint) {
return InjectionStrategy.NOARGUMENT;
}
else {
return InjectionStrategy.DEFAULTCASE;
}
}
}