package org.needle4j.injection; import java.lang.reflect.Field; import java.util.List; import org.needle4j.NeedleContext; import org.needle4j.annotation.InjectInto; import org.needle4j.annotation.InjectIntoMany; import org.needle4j.predicate.IsSupportedAnnotationPredicate; import org.needle4j.processor.NeedleProcessor; import org.needle4j.reflection.ReflectionUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class InjectionAnnotationProcessor implements NeedleProcessor { private final Logger logger = LoggerFactory.getLogger(InjectionAnnotationProcessor.class); private final IsSupportedAnnotationPredicate isSupportedAnnotationPredicate; public InjectionAnnotationProcessor(IsSupportedAnnotationPredicate isSupportedAnnotationPredicate) { this.isSupportedAnnotationPredicate = isSupportedAnnotationPredicate; } @Override public void process(final NeedleContext context) { proccessInjectIntoMany(context); proccessInjectInto(context); } private void proccessInjectIntoMany(final NeedleContext context) { Object testcase = context.getTest(); final List<Field> fieldsWithInjectIntoManyAnnotation = context.getAnnotatedTestcaseFields(InjectIntoMany.class); for (Field field : fieldsWithInjectIntoManyAnnotation) { final Object sourceObject = ReflectionUtil.getFieldValue(testcase, field); InjectIntoMany injectIntoManyAnnotation = field.getAnnotation(InjectIntoMany.class); InjectInto[] value = injectIntoManyAnnotation.value(); // inject into all object under test instance if (value.length == 0) { for (Object objectUnderTest : context.getObjectsUnderTest()) { injectByType(objectUnderTest, sourceObject, field.getType()); } } else { for (InjectInto injectInto : value) { processInjectInto(context, field, sourceObject, injectInto); } } } } private void proccessInjectInto(final NeedleContext context) { final Object testcase = context.getTest(); final List<Field> fields = context.getAnnotatedTestcaseFields(InjectInto.class); for (Field field : fields) { final Object sourceObject = ReflectionUtil.getFieldValue(testcase, field); processInjectInto(context, field, sourceObject, field.getAnnotation(InjectInto.class)); } } private void processInjectInto(final NeedleContext context, final Field field, final Object sourceObject, final InjectInto injectInto) { final Object object = context.getObjectUnderTest(injectInto.targetComponentId()); if (object != null) { if (injectInto.fieldName().equals("")) { injectByType(object, sourceObject, field.getType()); } else { injectByFieldName(object, sourceObject, injectInto.fieldName()); } } else { logger.warn("could not inject component {} - unknown object under test with id {}", sourceObject, injectInto.targetComponentId()); } } private void injectByType(final Object objectUnderTest, final Object sourceObject, final Class<?> type) { final List<Field> fields = ReflectionUtil.getAllFieldsAssinableFrom(type, objectUnderTest.getClass()); for (Field field : fields) { // skip injection when the field is not annotated with at least one // supported injection annotation if (!isSupportedAnnotationPredicate.applyAny(field.getDeclaredAnnotations())) { continue; } try { ReflectionUtil.setField(field, objectUnderTest, sourceObject); } catch (Exception e) { logger.warn("could not inject into component " + objectUnderTest, e); } } } private void injectByFieldName(final Object objectUnderTest, final Object sourceObject, final String fieldName) { try { ReflectionUtil.setField(fieldName, objectUnderTest, sourceObject); } catch (Exception e) { logger.warn("could not inject into component " + objectUnderTest, e); } } }