/*******************************************************************************
 * Copyright (c) 2009, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.e4.core.internal.di;

import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.eclipse.e4.core.di.IBinding;
import org.eclipse.e4.core.di.IInjector;
import org.eclipse.e4.core.di.InjectionException;
import org.eclipse.e4.core.di.annotations.Creatable;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.di.suppliers.ExtendedObjectSupplier;
import org.eclipse.e4.core.di.suppliers.IObjectDescriptor;
import org.eclipse.e4.core.di.suppliers.IRequestor;
import org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier;
import org.eclipse.e4.core.internal.di.osgi.DIActivator;
import org.eclipse.e4.core.internal.di.osgi.LogHelper;

/**
 * Reflection-based dependency injector.
 */
public class InjectorImpl implements IInjector {

	final static private String DEBUG_INJECTION = "org.eclipse.e4.core.di/debug/injector"; //$NON-NLS-1$
	final static private boolean shouldDebug = DIActivator.getDefault().getBooleanDebugOption(DEBUG_INJECTION, false);

	final static private String JAVA_OBJECT = "java.lang.Object"; //$NON-NLS-1$

	final private static Boolean DEFAULT_BOOLEAN = new Boolean(false);
	final private static Integer DEFAULT_INTEGER = new Integer(0);
	final private static Character DEFAULT_CHAR = new Character((char) 0);
	final private static Float DEFAULT_FLOAT = new Float(0.0f);
	final private static Double DEFAULT_DOUBLE = new Double(0.0d);
	final private static Long DEFAULT_LONG = new Long(0L);
	final private static Short DEFAULT_SHORT = new Short((short) 0);
	final private static Byte DEFAULT_BYTE = new Byte((byte) 0);

	private Map<PrimaryObjectSupplier, List<WeakReference<?>>> injectedObjects = new HashMap<PrimaryObjectSupplier, List<WeakReference<?>>>();
	private Set<WeakReference<Class<?>>> injectedClasses = new HashSet<WeakReference<Class<?>>>();
	private HashMap<Class<?>, Object> singletonCache = new HashMap<Class<?>, Object>();
	private Map<Class<?>, Set<Binding>> bindings = new HashMap<Class<?>, Set<Binding>>();

	// Performance improvement:
	private Map<Class<?>, Method[]> methodsCache = new WeakHashMap<Class<?>, Method[]>();
	private Map<Class<?>, Map<Method, Boolean>> isOverriddenCache = new WeakHashMap<Class<?>, Map<Method, Boolean>>();

	private Set<Class<?>> classesBeingCreated = new HashSet<Class<?>>(5);

	public void inject(Object object, PrimaryObjectSupplier objectSupplier) {
		inject(object, objectSupplier, null);
	}

	public void inject(Object object, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier) {
		// Two stages: first, go and collect {requestor, descriptor[] }
		ArrayList<Requestor> requestors = new ArrayList<Requestor>();
		processClassHierarchy(object, objectSupplier, tempSupplier, true /* track */, true /* normal order */, requestors);

		// if we are not establishing any links to the injected object (nothing to inject,
		// or constructor only), create a pseudo-link to track supplier's disposal
		boolean haveLink = false;
		for (Requestor requestor : requestors) {
			if (requestor.shouldTrack())
				haveLink = true;
		}
		if (!haveLink)
			requestors.add(new ClassRequestor(object.getClass(), this, objectSupplier, tempSupplier, object, true));

		// Then ask suppliers to fill actual values {requestor, descriptor[], actualvalues[] }
		resolveRequestorArgs(requestors, objectSupplier, tempSupplier, false, true, true);

		// Call requestors in order
		for (Requestor requestor : requestors) {
			if (requestor.isResolved())
				requestor.execute();
		}
		rememberInjectedObject(object, objectSupplier);

		// We call @PostConstruct after injection. This means that is is called 
		// as a part of both #make() and #inject().
		processAnnotated(PostConstruct.class, object, object.getClass(), objectSupplier, tempSupplier, new ArrayList<Class<?>>(5));

		// remove references to the temporary suppliers
		for (Requestor requestor : requestors) {
			requestor.clearTempSupplier();
		}
	}

	private void rememberInjectedObject(Object object, PrimaryObjectSupplier objectSupplier) {
		synchronized (injectedObjects) {
			List<WeakReference<?>> list;
			if (!injectedObjects.containsKey(objectSupplier)) {
				list = new ArrayList<WeakReference<?>>();
				injectedObjects.put(objectSupplier, list);
			} else
				list = injectedObjects.get(objectSupplier);
			for (WeakReference<?> ref : list) {
				if (object == ref.get())
					return; // we already have it
			}
			list.add(new WeakReference<Object>(object));
		}
	}

	private boolean forgetInjectedObject(Object object, PrimaryObjectSupplier objectSupplier) {
		synchronized (injectedObjects) {
			if (!injectedObjects.containsKey(objectSupplier))
				return false;
			List<WeakReference<?>> list = injectedObjects.get(objectSupplier);
			for (Iterator<WeakReference<?>> i = list.iterator(); i.hasNext();) {
				WeakReference<?> ref = i.next();
				if (object == ref.get()) {
					i.remove();
					return true;
				}
			}
			return false;
		}
	}

	private List<WeakReference<?>> forgetSupplier(PrimaryObjectSupplier objectSupplier) {
		synchronized (injectedObjects) {
			if (!injectedObjects.containsKey(objectSupplier))
				return null;
			return injectedObjects.remove(objectSupplier);
		}
	}

	private List<WeakReference<?>> getSupplierObjects(PrimaryObjectSupplier objectSupplier) {
		synchronized (injectedObjects) {
			if (!injectedObjects.containsKey(objectSupplier))
				return null;
			return injectedObjects.get(objectSupplier);
		}
	}

	public void uninject(Object object, PrimaryObjectSupplier objectSupplier) {
		if (!forgetInjectedObject(object, objectSupplier))
			return; // not injected at this time
		processAnnotated(PreDestroy.class, object, object.getClass(), objectSupplier, null, new ArrayList<Class<?>>(5));

		ArrayList<Requestor> requestors = new ArrayList<Requestor>();
		processClassHierarchy(object, objectSupplier, null, true /* track */, false /* inverse order */, requestors);

		for (Requestor requestor : requestors) {
			// Ask suppliers to fill actual values {requestor, descriptor[], actualvalues[] }
			Object[] actualArgs = resolveArgs(requestor, null, null, true, false, false);
			int unresolved = unresolved(actualArgs);
			if (unresolved == -1) {
				requestor.setResolvedArgs(actualArgs);
				requestor.execute();
			} else {
				if (requestor.isOptional())
					requestor.setResolvedArgs(null);
				else if (shouldDebug) {
					StringBuffer tmp = new StringBuffer();
					tmp.append("Uninjecting object \""); //$NON-NLS-1$
					tmp.append(object.toString());
					tmp.append("\": dependency on \""); //$NON-NLS-1$
					tmp.append(requestor.getDependentObjects()[unresolved].toString());
					tmp.append("\" is not optional."); //$NON-NLS-1$
					LogHelper.logError(tmp.toString(), null);
				}
			}
		}
	}

	public Object invoke(Object object, Class<? extends Annotation> qualifier, PrimaryObjectSupplier objectSupplier) {
		Object result = invokeUsingClass(object, object.getClass(), qualifier, IInjector.NOT_A_VALUE, objectSupplier, null, true);
		if (result == IInjector.NOT_A_VALUE)
			throw new InjectionException("Unable to find matching method to invoke"); //$NON-NLS-1$
		return result;
	}

	public Object invoke(Object object, Class<? extends Annotation> qualifier, Object defaultValue, PrimaryObjectSupplier objectSupplier) {
		return invokeUsingClass(object, object.getClass(), qualifier, defaultValue, objectSupplier, null, false);
	}

	public Object invoke(Object object, Class<? extends Annotation> qualifier, Object defaultValue, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier localSupplier) {
		return invokeUsingClass(object, object.getClass(), qualifier, defaultValue, objectSupplier, localSupplier, false);
	}

	private Object invokeUsingClass(Object userObject, Class<?> currentClass, Class<? extends Annotation> qualifier, Object defaultValue, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, boolean throwUnresolved) {
		Method[] methods = getDeclaredMethods(currentClass);
		for (int j = 0; j < methods.length; j++) {
			Method method = methods[j];
			if (method.getAnnotation(qualifier) == null)
				continue;
			MethodRequestor requestor = new MethodRequestor(method, this, objectSupplier, tempSupplier, userObject, false);

			Object[] actualArgs = resolveArgs(requestor, objectSupplier, tempSupplier, false, true, false);
			int unresolved = unresolved(actualArgs);
			if (unresolved != -1) {
				if (throwUnresolved)
					reportUnresolvedArgument(requestor, unresolved);
				continue;
			}
			requestor.setResolvedArgs(actualArgs);
			return requestor.execute();
		}
		Class<?> superClass = currentClass.getSuperclass();
		if (superClass == null)
			return defaultValue;

		return invokeUsingClass(userObject, superClass, qualifier, defaultValue, objectSupplier, tempSupplier, throwUnresolved);
	}

	public <T> T make(Class<T> clazz, PrimaryObjectSupplier objectSupplier) {
		Class<?> implementationClass = getImplementationClass(clazz);
		return clazz.cast(internalMake(implementationClass, objectSupplier, null));
	}

	private Class<?> getImplementationClass(Class<?> clazz) {
		IObjectDescriptor descriptor = new ObjectDescriptor(clazz, null);
		Binding binding = findBinding(descriptor);
		if (binding == null)
			return getDesiredClass(descriptor.getDesiredType());
		return binding.getImplementationClass();
	}

	public <T> T make(Class<T> clazz, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier staticSupplier) {
		Class<?> implementationClass = getImplementationClass(clazz);
		return clazz.cast(internalMake(implementationClass, objectSupplier, staticSupplier));
	}

	public Object makeFromProvider(IObjectDescriptor descriptor, PrimaryObjectSupplier objectSupplier) {
		Binding binding = findBinding(descriptor);
		Class<?> implementationClass;
		if (binding == null)
			implementationClass = getProviderType(descriptor.getDesiredType());
		else
			implementationClass = binding.getImplementationClass();
		if (objectSupplier != null) {
			IObjectDescriptor actualClass = new ObjectDescriptor(implementationClass, null);
			Object[] actualArgs = new Object[] {IInjector.NOT_A_VALUE};
			objectSupplier.get(new IObjectDescriptor[] {actualClass}, actualArgs, null, false, true, false);
			if (actualArgs[0] != IInjector.NOT_A_VALUE)
				return actualArgs[0];
		}
		return internalMake(implementationClass, objectSupplier, null);
	}

	private Object internalMake(Class<?> clazz, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier) {
		if (classesBeingCreated.contains(clazz))
			throw new InjectionException("Recursive reference trying to create class " + clazz.getName()); //$NON-NLS-1$
		try {
			classesBeingCreated.add(clazz);

			boolean isSingleton = clazz.isAnnotationPresent(Singleton.class);
			if (isSingleton) {
				synchronized (singletonCache) {
					if (singletonCache.containsKey(clazz))
						return singletonCache.get(clazz);
				}
			}

			Constructor<?>[] constructors = clazz.getDeclaredConstructors();
			// Sort the constructors by descending number of constructor arguments
			ArrayList<Constructor<?>> sortedConstructors = new ArrayList<Constructor<?>>(constructors.length);
			for (Constructor<?> constructor : constructors)
				sortedConstructors.add(constructor);
			Collections.sort(sortedConstructors, new Comparator<Constructor<?>>() {
				public int compare(Constructor<?> c1, Constructor<?> c2) {
					int l1 = c1.getParameterTypes().length;
					int l2 = c2.getParameterTypes().length;
					return l2 - l1;
				}
			});

			for (Constructor<?> constructor : sortedConstructors) {
				// skip private and protected constructors; allow public and package visibility
				int modifiers = constructor.getModifiers();
				if (((modifiers & Modifier.PRIVATE) != 0) || ((modifiers & Modifier.PROTECTED) != 0))
					continue;

				// unless this is the default constructor, it has to be tagged
				if (!constructor.isAnnotationPresent(Inject.class) && constructor.getParameterTypes().length != 0)
					continue;

				ConstructorRequestor requestor = new ConstructorRequestor(constructor, this, objectSupplier, tempSupplier);
				Object[] actualArgs = resolveArgs(requestor, objectSupplier, tempSupplier, false, true, false);
				if (unresolved(actualArgs) != -1)
					continue;
				requestor.setResolvedArgs(actualArgs);

				Object newInstance = requestor.execute();
				if (newInstance != null) {
					inject(newInstance, objectSupplier, tempSupplier);
					if (isSingleton) {
						synchronized (singletonCache) { // TBD this is not quite right, synch the method
							singletonCache.put(clazz, newInstance);
						}
					}
					return newInstance;
				}
			}
			throw new InjectionException("Could not find satisfiable constructor in " + clazz.getName()); //$NON-NLS-1$
		} finally {
			classesBeingCreated.remove(clazz);
		}
	}

	public void resolveArguments(IRequestor requestor, boolean initial) {
		Requestor internalRequestor = ((Requestor) requestor);
		Object[] actualArgs = resolveArgs(internalRequestor, internalRequestor.getPrimarySupplier(), internalRequestor.getTempSupplier(), false, initial, internalRequestor.shouldTrack());
		int unresolved = unresolved(actualArgs);
		if (unresolved == -1)
			internalRequestor.setResolvedArgs(actualArgs);
		else {
			if (internalRequestor.isOptional())
				internalRequestor.setResolvedArgs(null);
			else {
				String msg = resolutionError(internalRequestor, unresolved);
				LogHelper.logError(msg, null);
			}
		}
	}

	public void disposed(PrimaryObjectSupplier objectSupplier) {
		List<WeakReference<?>> references = getSupplierObjects(objectSupplier);
		if (references == null)
			return;
		Object[] objects = new Object[references.size()];
		int count = 0;
		for (WeakReference<?> ref : references) {
			Object object = ref.get();
			if (object != null) {
				objects[count] = object;
				count++;
			}
		}
		for (int i = 0; i < count; i++) {
			Object object = objects[i];
			if (!forgetInjectedObject(object, objectSupplier))
				continue; // not injected at this time
			processAnnotated(PreDestroy.class, object, object.getClass(), objectSupplier, null, new ArrayList<Class<?>>(5));
		}
		forgetSupplier(objectSupplier);
	}

	private void resolveRequestorArgs(ArrayList<Requestor> requestors, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, boolean uninject, boolean initial, boolean track) {
		for (Requestor requestor : requestors) {
			Object[] actualArgs = resolveArgs(requestor, objectSupplier, tempSupplier, uninject, initial, track);
			int unresolved = unresolved(actualArgs);
			if (unresolved == -1) {
				requestor.setResolvedArgs(actualArgs);
				continue;
			}

			if (requestor.isOptional())
				requestor.setResolvedArgs(null);
			else
				reportUnresolvedArgument(requestor, unresolved);
		}
	}

	private void reportUnresolvedArgument(Requestor requestor, int argIndex) {
		String msg = resolutionError(requestor, argIndex);
		if (shouldDebug) {
			LogHelper.logError(msg, null);
		}
		throw new InjectionException(msg);
	}

	private String resolutionError(Requestor requestor, int argIndex) {
		StringBuffer tmp = new StringBuffer();
		tmp.append("Unable to process \""); //$NON-NLS-1$
		tmp.append(requestor.toString());
		tmp.append("\": no actual value was found for the argument \""); //$NON-NLS-1$
		tmp.append(requestor.getDependentObjects()[argIndex].toString());
		tmp.append("\"."); //$NON-NLS-1$
		return tmp.toString();
	}

	private Object[] resolveArgs(Requestor requestor, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, boolean uninject, boolean initial, boolean track) {
		IObjectDescriptor[] descriptors = requestor.getDependentObjects();

		// 0) initial fill - all values are unresolved
		Object[] actualArgs = new Object[descriptors.length];
		Arrays.fill(actualArgs, NOT_A_VALUE);

		// 1) check if we have a Provider<T>
		for (int i = 0; i < actualArgs.length; i++) {
			Class<?> providerClass = getProviderType(descriptors[i].getDesiredType());
			if (providerClass == null)
				continue;
			actualArgs[i] = new ProviderImpl<Class<?>>(descriptors[i], this, objectSupplier);
		}

		// 2) use the temporary supplier
		if (tempSupplier != null)
			tempSupplier.get(descriptors, actualArgs, requestor, initial, false /* no tracking */, requestor.shouldGroupUpdates());

		// 3) use the primary supplier
		if (objectSupplier != null)
			objectSupplier.get(descriptors, actualArgs, requestor, initial, requestor.shouldTrack() && track, requestor.shouldGroupUpdates());

		// 4) try extended suppliers
		for (int i = 0; i < actualArgs.length; i++) {
			if (actualArgs[i] != NOT_A_VALUE)
				continue; // already resolved
			ExtendedObjectSupplier extendedSupplier = findExtendedSupplier(descriptors[i], objectSupplier);
			if (extendedSupplier == null)
				continue;
			actualArgs[i] = extendedSupplier.get(descriptors[i], requestor, requestor.shouldTrack() && track, requestor.shouldGroupUpdates());
		}

		// 5) try the bindings
		for (int i = 0; i < actualArgs.length; i++) {
			if (actualArgs[i] != NOT_A_VALUE)
				continue; // already resolved
			Binding binding = findBinding(descriptors[i]);
			if (binding != null)
				actualArgs[i] = internalMake(binding.getImplementationClass(), objectSupplier, tempSupplier);
		}

		// 5) create simple classes (implied bindings) - unless we uninject or optional
		if (!uninject && !requestor.isOptional()) {
			for (int i = 0; i < actualArgs.length; i++) {
				if (actualArgs[i] != NOT_A_VALUE)
					continue; // already resolved
				if (descriptors[i].hasQualifier(Optional.class))
					continue;
				try {
					Class<?> desiredClass = getDesiredClass(descriptors[i].getDesiredType());
					Creatable creatableAnnotation = desiredClass.getAnnotation(Creatable.class);
					if (creatableAnnotation == null)
						continue;
					actualArgs[i] = internalMake(getDesiredClass(descriptors[i].getDesiredType()), objectSupplier, tempSupplier);
				} catch (InjectionException e) {
					// ignore
				}
			}
		}

		// 6) post process
		for (int i = 0; i < descriptors.length; i++) {
			// check that values are of a correct type
			if (actualArgs[i] != null && actualArgs[i] != IInjector.NOT_A_VALUE) {
				Class<?> descriptorsClass = getDesiredClass(descriptors[i].getDesiredType());
				if (descriptorsClass.isPrimitive()) { // support type autoboxing
					if (descriptorsClass.equals(boolean.class))
						descriptorsClass = Boolean.class;
					else if (descriptorsClass.equals(int.class))
						descriptorsClass = Integer.class;
					else if (descriptorsClass.equals(char.class))
						descriptorsClass = Character.class;
					else if (descriptorsClass.equals(float.class))
						descriptorsClass = Float.class;
					else if (descriptorsClass.equals(double.class))
						descriptorsClass = Double.class;
					else if (descriptorsClass.equals(long.class))
						descriptorsClass = Long.class;
					else if (descriptorsClass.equals(short.class))
						descriptorsClass = Short.class;
					else if (descriptorsClass.equals(byte.class))
						descriptorsClass = Byte.class;
				}
				if (!descriptorsClass.isAssignableFrom(actualArgs[i].getClass()))
					actualArgs[i] = IInjector.NOT_A_VALUE;
			}
			if (actualArgs[i] == IInjector.NOT_A_VALUE) { // still unresolved?
				if (descriptors[i].hasQualifier(Optional.class)) { // uninject or optional - fill defaults
					Class<?> descriptorsClass = getDesiredClass(descriptors[i].getDesiredType());
					if (descriptorsClass.isPrimitive()) {
						if (descriptorsClass.equals(boolean.class))
							actualArgs[i] = DEFAULT_BOOLEAN;
						else if (descriptorsClass.equals(int.class))
							actualArgs[i] = DEFAULT_INTEGER;
						else if (descriptorsClass.equals(char.class))
							actualArgs[i] = DEFAULT_CHAR;
						else if (descriptorsClass.equals(float.class))
							actualArgs[i] = DEFAULT_FLOAT;
						else if (descriptorsClass.equals(double.class))
							actualArgs[i] = DEFAULT_DOUBLE;
						else if (descriptorsClass.equals(long.class))
							actualArgs[i] = DEFAULT_LONG;
						else if (descriptorsClass.equals(short.class))
							actualArgs[i] = DEFAULT_SHORT;
						else if (descriptorsClass.equals(byte.class))
							actualArgs[i] = DEFAULT_BYTE;
					} else
						actualArgs[i] = null;
				}
			}
		}
		return actualArgs;
	}

	private ExtendedObjectSupplier findExtendedSupplier(IObjectDescriptor descriptor, PrimaryObjectSupplier objectSupplier) {
		Annotation[] qualifiers = descriptor.getQualifiers();
		if (qualifiers == null)
			return null;
		for (Annotation qualifier : qualifiers) {
			String key;
			Type type = qualifier.annotationType();
			if (type instanceof Class<?>) {
				key = ((Class<?>) type).getName();
			} else
				continue;

			ExtendedObjectSupplier supplier;
			try {
				// use qualified name to refer to a class that might be missing
				supplier = org.eclipse.e4.core.internal.di.osgi.ProviderHelper.findProvider(key, objectSupplier);
			} catch (NoClassDefFoundError e) {
				return null; // OSGi framework not present 
			}
			if (supplier != null)
				return supplier;
		}
		return null;
	}

	private int unresolved(Object[] actualArgs) {
		for (int i = 0; i < actualArgs.length; i++) {
			if (actualArgs[i] == IInjector.NOT_A_VALUE)
				return i;
		}
		return -1;
	}

	private void processClassHierarchy(Object userObject, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, boolean track, boolean normalOrder, List<Requestor> requestors) {
		processClass(userObject, objectSupplier, tempSupplier, (userObject == null) ? null : userObject.getClass(), new ArrayList<Class<?>>(5), track, normalOrder, requestors);
	}

	/**
	 * Make the processor visit all declared members on the given class and all superclasses
	 */
	private void processClass(Object userObject, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, Class<?> objectsClass, ArrayList<Class<?>> classHierarchy, boolean track, boolean normalOrder, List<Requestor> requestors) {
		// order: superclass, fields, methods
		if (objectsClass != null) {
			Class<?> superClass = objectsClass.getSuperclass();
			if (superClass != null && !superClass.getName().equals(JAVA_OBJECT)) {
				classHierarchy.add(objectsClass);
				processClass(userObject, objectSupplier, tempSupplier, superClass, classHierarchy, track, normalOrder, requestors);
				classHierarchy.remove(objectsClass);
			}
		}
		boolean injectedStaticFields;
		boolean injectedStaticMethods;
		if (normalOrder) {
			injectedStaticFields = processFields(userObject, objectSupplier, tempSupplier, objectsClass, track, requestors);
			injectedStaticMethods = processMethods(userObject, objectSupplier, tempSupplier, objectsClass, classHierarchy, track, requestors);
		} else {
			injectedStaticMethods = processMethods(userObject, objectSupplier, tempSupplier, objectsClass, classHierarchy, track, requestors);
			injectedStaticFields = processFields(userObject, objectSupplier, tempSupplier, objectsClass, track, requestors);
		}
		if (injectedStaticFields || injectedStaticMethods)
			rememberInjectedStatic(objectsClass);
	}

	private boolean hasInjectedStatic(Class<?> objectsClass) {
		synchronized (injectedClasses) {
			for (WeakReference<Class<?>> ref : injectedClasses) {
				Class<?> injectedClass = ref.get();
				if (injectedClass == null)
					continue;
				if (injectedClass == objectsClass) // use pointer comparison
					return true;
			}
			return false;
		}
	}

	private void rememberInjectedStatic(Class<?> objectsClass) {
		synchronized (injectedClasses) {
			injectedClasses.add(new WeakReference<Class<?>>(objectsClass));
		}
	}

	/**
	 * Make the processor visit all declared fields on the given class.
	 */
	private boolean processFields(Object userObject, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, Class<?> objectsClass, boolean track, List<Requestor> requestors) {
		boolean injectedStatic = false;
		Field[] fields = objectsClass.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			if (Modifier.isStatic(field.getModifiers())) {
				if (hasInjectedStatic(objectsClass))
					continue;
				injectedStatic = true;
			}
			if (!field.isAnnotationPresent(Inject.class))
				continue;
			requestors.add(new FieldRequestor(field, this, objectSupplier, tempSupplier, userObject, track));
		}
		return injectedStatic;
	}

	/**
	 * Make the processor visit all declared methods on the given class.
	 */
	private boolean processMethods(final Object userObject, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, Class<?> objectsClass, ArrayList<Class<?>> classHierarchy, boolean track, List<Requestor> requestors) {
		boolean injectedStatic = false;
		Method[] methods = getDeclaredMethods(objectsClass);
		for (int i = 0; i < methods.length; i++) {
			final Method method = methods[i];

			Boolean isOverridden = null;
			Map<Method, Boolean> methodMap = null;
			Class<?> originalClass = userObject.getClass();
			if (isOverriddenCache.containsKey(originalClass)) {
				methodMap = isOverriddenCache.get(originalClass);
				if (methodMap.containsKey(method))
					isOverridden = methodMap.get(method);
			}
			if (isOverridden == null) {
				isOverridden = isOverridden(method, classHierarchy);
				if (methodMap == null) {
					methodMap = new WeakHashMap<Method, Boolean>();
					isOverriddenCache.put(originalClass, methodMap);
				}
				methodMap.put(method, isOverridden);
			}

			if (isOverridden)
				continue; // process in the subclass
			if (Modifier.isStatic(method.getModifiers())) {
				if (hasInjectedStatic(objectsClass))
					continue;
				injectedStatic = true;
			}
			if (!method.isAnnotationPresent(Inject.class))
				continue;
			requestors.add(new MethodRequestor(method, this, objectSupplier, tempSupplier, userObject, track));
		}
		return injectedStatic;
	}

	/**
	 * Checks if a given method is overridden with an injectable method.
	 */
	private boolean isOverridden(Method method, ArrayList<Class<?>> classHierarchy) {
		int modifiers = method.getModifiers();
		if (Modifier.isPrivate(modifiers))
			return false;
		if (Modifier.isStatic(modifiers))
			return false;
		// method is not private if we reached this line, check not(public OR protected)
		boolean isDefault = !(Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers));

		String methodName = method.getName();
		Class<?>[] methodParams = method.getParameterTypes();
		int methodParamsLength = method.getParameterTypes().length;
		for (Class<?> subClass : classHierarchy) {
			Method[] methods = getDeclaredMethods(subClass);
			Method matchingMethod = null;
			for (Method candidate : methods) {
				if (!methodName.equals(candidate.getName()))
					continue;
				Class<?>[] candidateParams = candidate.getParameterTypes();
				if (candidateParams.length != methodParamsLength)
					continue;
				boolean paramsMatch = true;
				for (int i = 0; i < methodParamsLength; i++) {
					if (candidateParams[i].equals(methodParams[i])) // strictly speaking, need to add erasures
						continue;
					paramsMatch = false;
				}
				if (!paramsMatch)
					continue;
				matchingMethod = candidate;
				break;
			}
			if (matchingMethod == null)
				continue;

			if (isDefault) { // must be in the same package to override
				Package originalPackage = method.getDeclaringClass().getPackage();
				Package overridePackage = subClass.getPackage();

				if (originalPackage == null && overridePackage == null)
					return true;
				if (originalPackage == null || overridePackage == null)
					return false;
				if (originalPackage.equals(overridePackage))
					return true;
			} else
				return true;
		}
		return false;
	}

	private Method[] getDeclaredMethods(Class<?> c) {
		Method[] methods = methodsCache.get(c);
		if (methods == null) {
			methods = c.getDeclaredMethods();
			methodsCache.put(c, methods);
		}
		return methods;
	}

	private Class<?> getDesiredClass(Type desiredType) {
		if (desiredType instanceof Class<?>)
			return (Class<?>) desiredType;
		if (desiredType instanceof ParameterizedType) {
			Type rawType = ((ParameterizedType) desiredType).getRawType();
			if (rawType instanceof Class<?>)
				return (Class<?>) rawType;
		}
		return null;
	}

	/**
	 * Returns null if not a provider
	 */
	private Class<?> getProviderType(Type type) {
		if (!(type instanceof ParameterizedType))
			return null;
		Type rawType = ((ParameterizedType) type).getRawType();
		if (!Provider.class.equals(rawType))
			return null;
		Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments();
		if (actualTypes.length != 1)
			return null;
		if (!(actualTypes[0] instanceof Class<?>))
			return null;
		return (Class<?>) actualTypes[0];
	}

	public IBinding addBinding(Class<?> clazz) {
		return addBinding(new Binding(clazz, this));
	}

	public IBinding addBinding(IBinding binding) {
		Binding internalBinding = (Binding) binding;
		Class<?> clazz = internalBinding.getDescribedClass();
		synchronized (bindings) {
			if (bindings.containsKey(clazz)) {
				Set<Binding> collection = bindings.get(clazz);
				String desiredQualifierName = internalBinding.getQualifierName();
				for (Iterator<Binding> i = collection.iterator(); i.hasNext();) {
					Binding collectionBinding = i.next();
					if (eq(collectionBinding.getQualifierName(), desiredQualifierName)) {
						i.remove();
						break;
					}
				}
				collection.add(internalBinding);
			} else {
				Set<Binding> collection = new HashSet<Binding>(1);
				collection.add(internalBinding);
				bindings.put(clazz, collection);
			}
		}
		return binding;
	}

	private Binding findBinding(IObjectDescriptor descriptor) {
		Class<?> desiredClass = getProviderType(descriptor.getDesiredType());
		if (desiredClass == null)
			desiredClass = getDesiredClass(descriptor.getDesiredType());
		synchronized (bindings) {
			if (!bindings.containsKey(desiredClass))
				return null;
			Set<Binding> collection = bindings.get(desiredClass);
			String desiredQualifierName = null;
			if (descriptor.hasQualifier(Named.class)) {
				Named namedAnnotation = descriptor.getQualifier(Named.class);
				desiredQualifierName = namedAnnotation.value();
			} else {
				Annotation[] annotations = descriptor.getQualifiers();
				if (annotations != null) {
					for (Annotation annotation : annotations) {
						desiredQualifierName = annotation.annotationType().getName();
						break;
					}
				}
			}

			for (Iterator<Binding> i = collection.iterator(); i.hasNext();) {
				Binding collectionBinding = i.next();
				if (eq(collectionBinding.getQualifierName(), desiredQualifierName))
					return collectionBinding;
			}
			desiredQualifierName = desiredClass.getName();
			for (Iterator<Binding> i = collection.iterator(); i.hasNext();) {
				Binding collectionBinding = i.next();
				Class<?> bindingClass = collectionBinding.getDescribedClass();
				if (bindingClass == null)
					continue;
				String simpleClassName = bindingClass.getName();
				if (eq(simpleClassName, desiredQualifierName))
					return collectionBinding;
			}
		}
		return null;
	}

	/**
	 * Are two, possibly null, string equal?
	 */
	private boolean eq(String str1, String str2) {
		if (str1 == null && str2 == null)
			return true;
		if (str1 == null || str2 == null)
			return false;
		return str1.equals(str2);
	}

	private void processAnnotated(Class<? extends Annotation> annotation, Object userObject, Class<?> objectClass, PrimaryObjectSupplier objectSupplier, PrimaryObjectSupplier tempSupplier, ArrayList<Class<?>> classHierarchy) {
		Class<?> superClass = objectClass.getSuperclass();
		if (superClass != null && !superClass.getName().equals(JAVA_OBJECT)) {
			classHierarchy.add(objectClass);
			processAnnotated(annotation, userObject, superClass, objectSupplier, tempSupplier, classHierarchy);
			classHierarchy.remove(objectClass);
		}
		Method[] methods = getDeclaredMethods(objectClass);
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			if (!method.isAnnotationPresent(annotation))
				continue;
			if (isOverridden(method, classHierarchy))
				continue;

			MethodRequestor requestor = new MethodRequestor(method, this, objectSupplier, tempSupplier, userObject, false);
			Object[] actualArgs = resolveArgs(requestor, objectSupplier, tempSupplier, false, false, false);
			int unresolved = unresolved(actualArgs);
			if (unresolved != -1) {
				if (method.isAnnotationPresent(Optional.class))
					continue;
				reportUnresolvedArgument(requestor, unresolved);
			}
			requestor.setResolvedArgs(actualArgs);
			requestor.execute();
		}
	}

}
