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

org.popper.fw.impl.AbstractPopperContext Maven / Gradle / Ivy

Go to download

Definition of the interfaces all Popper Framework implementations depend on

The newest version!
/*
 * Copyright [2013] [Michael Bulla, [email protected]]
 *
 * 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.popper.fw.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.popper.fw.annotations.DefaultConstructor;
import org.popper.fw.annotations.ElementFactory;
import org.popper.fw.annotations.Type;
import org.popper.fw.interfaces.IClassResolver;
import org.popper.fw.interfaces.IElementFactory;
import org.popper.fw.interfaces.IPoFactory;

public abstract class AbstractPopperContext {
	private IElementFactory defaultElementFactory;
	
	private IClassResolver classResolver;

	public abstract IPoFactory getFactory();

	public IElementFactory getDefaultElementFactory() {
		return defaultElementFactory;
	}
	
	public void setDefaultElementFactory(IElementFactory defaultElementFactory) {
		this.defaultElementFactory = defaultElementFactory;
	}
	
	public IClassResolver getClassResolver() {
		return classResolver;
	}

	public void setClassResolver(IClassResolver classResolver) {
		this.classResolver = classResolver;
	}

	public Class getImplementingClassFor(Method method, Class clazz) {
		Type typeAnnoation = method.getAnnotation(Type.class);
		if (typeAnnoation != null) {
			return typeAnnoation.value();
		}

		ElementFactory elementFactory = method.getDeclaringClass().getAnnotation(ElementFactory.class);
		if (elementFactory != null) {
			try {
				return elementFactory.value().newInstance().getImplClassForElement(clazz);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}

		if (defaultElementFactory != null) {
			Class ret = defaultElementFactory.getImplClassForElement(clazz);
			if (ret != null) {
				return ret;
			}
		}
		
		if (!clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) {
			return clazz;
		}

		return null;
	}
	
	public final T instantiateObject(Class type, Map, Object> tempResolver) {
		return new ObjectInstantiator().instantiateObject(type, classResolver, tempResolver);
	}
	
	public final T instantiateObject(Class type) {
		return instantiateObject(type, null);
	}
	
	public static String replaceVariables(String input, Object[] parameters) {
		if (parameters != null) {
			for (int i = 0; i < parameters.length; i++) {
				String replace = "";
				if (parameters[i] != null) {
					replace = parameters[i].toString();
				}
				input = input.replace("{" + i + "}", replace);
			}
		}
		return input;
	}
	
	public static class ObjectInstantiator {
		private static final Logger log = Logger.getLogger(ObjectInstantiator.class);
		
		public final T instantiateObject(Class type, IClassResolver classResolver, Map, Object> tempResolver) {
			log.info("Instantiating Object of class " + type.getName());
			Constructor constructor = getConstructorToUse(type);
			Object[] parameters = getParameters(type, classResolver, tempResolver);
			
			try {
				T ret = constructor.newInstance(parameters);
				return ret;
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		
		public Object[] getParameters(Class type, IClassResolver classResolver, Map, Object> tempResolver) {
			if (tempResolver == null) {
				tempResolver = new HashMap, Object>();
			}
			Class[] parameterTypes = getConstructorDefinition(type);
			Object[] parameters = new Object[parameterTypes.length];
			for (int i = 0; i < parameterTypes.length; i++) {
				Object o = tempResolver.get(parameterTypes[i]);
				
				if (o == null) {
					o = classResolver.resolveClass(parameterTypes[i]);
				}
				
				if (o == null) {
					throw new RuntimeException("There is no Resolver defined to resolve class " + parameterTypes[i].getName() + " when instantiating object of type " + type.getName());
				}
				parameters[i] = o;
			}
			
			return parameters;
			
		}
		
		public Class[] getConstructorDefinition(Class clazz) {
			return getConstructorToUse(clazz).getParameterTypes();
		}
		
		@SuppressWarnings("unchecked")
		private static Constructor getConstructorToUse(Class type) {
			Constructor[] constructors = (Constructor[]) type.getConstructors();
			if (constructors.length == 1) {
				return constructors[0];
			}
			
			Constructor ret = null;
			for (Constructor constructor : constructors) {
				DefaultConstructor ec = constructor.getAnnotation(DefaultConstructor.class);
				if (ec != null) {
					if (ret != null) {
						throw new RuntimeException("There are at least 2 Constructors annotated with @ElementConstructor for class " + type.getName() + ": " + ret + ", " + constructor + ". There is only one such Annotation allowed.");
					}
					ret = constructor;
				}
			}
			
			if (ret == null) {
				throw new RuntimeException("There could be no Constructor determindened to instantiate " + type.getName() + ". Provide only one constructor or annotate the none to be used with @ElementConstructor.");
			}
			return ret;
		}
	}
}






© 2015 - 2025 Weber Informatics LLC | Privacy Policy