All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unidal.lookup.ComponentTestCase Maven / Gradle / Ivy

The newest version!
package org.unidal.lookup;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.unidal.helper.Reflects;
import org.unidal.helper.Reflects.IMemberFilter;
import org.unidal.helper.Threads;
import org.unidal.lookup.annotation.Inject;
import org.unidal.lookup.annotation.Named;
import org.unidal.lookup.container.model.entity.Any;
import org.unidal.lookup.container.model.entity.ComponentModel;
import org.unidal.lookup.container.model.entity.ConfigurationModel;
import org.unidal.lookup.container.model.entity.RequirementModel;

public abstract class ComponentTestCase extends ContainerHolder {
   private PlexusContainer m_container;

   private Class getElementType(Field field) {
      Type type = field.getGenericType();
      Class clazz = field.getType();

      if (clazz.isArray()) {
         return clazz.getComponentType();
      } else {
         if (type instanceof ParameterizedType) {
            Type[] args = ((ParameterizedType) type).getActualTypeArguments();

            if (clazz == List.class || clazz == Set.class) {
               if (args.length == 1) {
                  return (Class) args[0];
               }
            } else if (clazz == Map.class) {
               if (args.length == 2) {
                  return (Class) args[1];
               }
            }
         }
      }

      return field.getType();
   }

   protected  ComponentDefinition define(Class implementation) throws Exception {
      Named named = implementation.getAnnotation(Named.class);

      if (named == null) {
         String name = implementation.getName();

         throw new IllegalArgumentException(String.format("Class(%s) should be annotated with @Named!", name));
      }

      String roleHint = (named.value().length() > 0 ? named.value() : null);

      return define(implementation, roleHint);
   }

   @SuppressWarnings("unchecked")
   protected  ComponentDefinition define(Class implementation, String roleHint) throws Exception {
      Named named = implementation.getAnnotation(Named.class);

      if (named == null) {
         String name = implementation.getName();

         throw new IllegalArgumentException(String.format("Class(%s) should be annotated with @Named!", name));
      }

      Class role = (named.type() != Named.Default.class ? (Class) named.type() : implementation);
      ComponentDefinition component = defineComponent(role, roleHint, implementation);

      if (named.instantiationStrategy().length() > 0) {
         component.is(named.instantiationStrategy());
      } else if (implementation.isEnum()) {
         component.is(Named.ENUM);
      }

      defineDependencies(component, implementation);
      return component;
   }

   protected  ComponentDefinition defineComponent(Class role) throws Exception {
      return defineComponent(role, null, role);
   }

   protected  ComponentDefinition defineComponent(Class role, Class implementation)
         throws Exception {
      return defineComponent(role, null, implementation);
   }

   protected  ComponentDefinition defineComponent(Class role, String roleHint,
         Class implementation) throws Exception {
      ComponentModel model = new ComponentModel();

      model.setImplementation(implementation.getName());
      model.setRole(role.getName());

      if (roleHint != null) {
         model.setRoleHint(roleHint);
      }

      getContainer().addComponentModel(model);
      return new ComponentDefinition(model);
   }

   private  void defineDependencies(ComponentDefinition component, Class implementation) {
      List fields = Reflects.forField().getAllDeclaredFields(implementation, new IMemberFilter() {
         @Override
         public boolean filter(Field member) {
            return member.isAnnotationPresent(Inject.class);
         }
      });

      for (Field field : fields) {
         defineDependency(component, field);
      }
   }

   private void defineDependency(ComponentDefinition component, Field field) {
      Inject inject = field.getAnnotation(Inject.class);

      if (inject != null) {
         Class role = inject.type();
         String[] roleHints = inject.value();
         Class type = field.getType();
         Class elementType = getElementType(field);

         if (role == Inject.Default.class) {
            role = elementType;
         }

         if (type == elementType) { // normal simple case
            if (roleHints.length == 0) {
               component.req(role);
            } else if (roleHints.length == 1) {
               component.req(role, roleHints[0]);
            } else {
               component.req(role, roleHints, field.getName());
            }
         } else { // List, Set or Array
            if (roleHints.length == 0) {
               component.req(role, null, field.getName());
            } else {
               component.req(role, roleHints, field.getName());
            }
         }
      }
   }

   @Override
   protected PlexusContainer getContainer() {
      return m_container;
   }

   @Before
   public void setUp() throws Exception {
      String configuration = getClass().getName().replace('.', '/') + ".xml";

      ContainerLoader.destroy();
      m_container = ContainerLoader.getDefaultContainer(configuration);
      System.setProperty("devMode", "true");
   }

   @After
   public void tearDown() throws Exception {
      ContainerLoader.destroy();
      Threads.reset();
      m_container = null;
   }

   protected static final class ComponentDefinition {
      private ComponentModel m_model;

      public ComponentDefinition(ComponentModel descriptor) {
         m_model = descriptor;
      }

      public ComponentDefinition config(String name, String value) {
         Any element = new Any().setName(name).setValue(value);
         ConfigurationModel config = m_model.getConfiguration();

         if (config == null) {
            config = new ConfigurationModel();
            m_model.setConfiguration(config);
         }

         config.getDynamicElements().add(element);
         return this;
      }

      public ComponentDefinition is(String instantiationStrategy) {
         m_model.setInstantiationStrategy(instantiationStrategy);
         return this;
      }

      public ComponentDefinition req(Class role) {
         return req(role, null);
      }

      public ComponentDefinition req(Class role, String roleHint) {
         RequirementModel requirement = new RequirementModel();

         requirement.setRole(role.getName());

         if (roleHint != null) {
            requirement.setRoleHint(roleHint);
         }

         m_model.addRequirement(requirement);
         return this;
      }

      public ComponentDefinition req(Class role, String[] roleHints, String fieldName) {
         RequirementModel requirement = new RequirementModel();

         requirement.setRole(role.getName());
         requirement.setFieldName(fieldName);

         if (roleHints != null && roleHints.length > 0) {
            Any hints = new Any().setName("role-hints");

            requirement.getDynamicElements().add(hints);

            for (String roleHint : roleHints) {
               hints.addChild(new Any().setName("role-hint").setValue(roleHint));
            }
         }

         m_model.addRequirement(requirement);
         return this;
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy