/*******************************************************************************
 * Copyright (c) 2009, 2010 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.services.internal.context;

import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
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.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 javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.core.services.IDisposable;
import org.eclipse.e4.core.services.context.IEclipseContext;
import org.eclipse.e4.core.services.context.spi.ContextInjectionFactory;
import org.eclipse.e4.core.services.context.spi.IContextConstants;
import org.eclipse.e4.core.services.injector.AbstractObjectSupplier;
import org.eclipse.e4.core.services.injector.IBinding;
import org.eclipse.e4.core.services.injector.IInjector;
import org.eclipse.e4.core.services.injector.IObjectDescriptor;
import org.eclipse.e4.core.services.injector.IRequestor;
import org.eclipse.e4.core.services.injector.ObjectDescriptorFactory;
import org.eclipse.e4.core.services.internal.annotations.AnnotationsSupport;

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

	final static private String JAVA_OBJECT = "java.lang.Object"; //$NON-NLS-1$
	// XXX remove
	// plug-in class that gets replaced in Java 1.5+
	final private static AnnotationsSupport annotationSupport = new AnnotationsSupport();

	// TBD thread safety
	private Map<String, AbstractObjectSupplier> extendedSuppliers = new HashMap<String, AbstractObjectSupplier>();

	private Map<AbstractObjectSupplier, List<WeakReference<?>>> injectedObjects = new HashMap<AbstractObjectSupplier, List<WeakReference<?>>>();
	private HashMap<Class<?>, Object> singletonCache = new HashMap<Class<?>, Object>();
	private Map<Class<?>, Set<IBinding>> bindings = new HashMap<Class<?>, Set<IBinding>>();

	public boolean inject(Object object, AbstractObjectSupplier objectSupplier) {
		// Two stages: first, go and collect {requestor, descriptor[] }
		ArrayList<Requestor> requestors = new ArrayList<Requestor>();
		processClassHierarchy(object, false /* no static */, true /* track */, true /* normal order */,
				requestors);
		// Ask suppliers to fill actual values {requestor, descriptor[], actualvalues[] }
		if (!resolveRequestorArgs(requestors, objectSupplier, false))
			return false;

		// Call requestors in order
		for (Requestor requestor : requestors) {
			try {
				if (requestor.isResolved())
					requestor.execute();
			} catch (InvocationTargetException e) {
				logError("Injection failed for the object \"" + object.toString()
						+ "\". Unable to execute \"" + requestor.toString() + "\"");
				return false;
			} catch (InstantiationException e) {
				logError("Injection failed for the object \"" + object.toString()
						+ "\". Unable to execute \"" + requestor.toString() + "\"");
				return false;
			}
		}
		rememberInjectedObject(object, objectSupplier);

		// TBD current tests assume that @PostConstruct methods will be
		// called after injection; however, name implies that it is only
		// called when the object is constructed. Fix this after the 1.4/1.5 merge.
		try {
			processPostConstruct(object, object.getClass(), objectSupplier,
					new ArrayList<Class<?>>(5));
		} catch (InvocationTargetException e) {
			logError("Injection failed for the object \"" + object.toString()
					+ "\". Unable to process post-construct methods.", e);
			return false;
		} catch (InstantiationException e) {
			logError("Injection failed for the object \"" + object.toString()
					+ "\". Unable to process post-construct methods.", e);
			return false;
		}
		return true;
	}

	private void rememberInjectedObject(Object object, AbstractObjectSupplier 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, AbstractObjectSupplier 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(AbstractObjectSupplier objectSupplier) {
		synchronized (injectedObjects) {
			if (!injectedObjects.containsKey(objectSupplier))
				return null;
			return injectedObjects.remove(objectSupplier);
		}
	}

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

	public boolean uninject(Object object, AbstractObjectSupplier objectSupplier) {
		if (!forgetInjectedObject(object, objectSupplier))
			return false; // not injected at this time
		// Two stages: first, go and collect {requestor, descriptor[] }
		ArrayList<Requestor> requestors = new ArrayList<Requestor>();
		processClassHierarchy(object, false /* no static */, true /* track */,
				false /* inverse order */, requestors);
		// might still need to get resolved values from secondary suppliers
		// Ask suppliers to fill actual values {requestor, descriptor[], actualvalues[] }
		if (!resolveRequestorArgs(requestors, null, true /* fill with nulls */))
			return false;

		// Call requestors in order
		for (Requestor requestor : requestors) {
			try {
				requestor.execute();
			} catch (InvocationTargetException e) {
				logError("Uninjection failed for the object \"" + object.toString()
						+ "\". Unable to execute \"" + requestor.toString() + "\"");
				return false;
			} catch (InstantiationException e) {
				logError("Uninjection failed for the object \"" + object.toString()
						+ "\". Unable to execute \"" + requestor.toString() + "\"");
				return false;
			}
		}
		return true;
	}

	public Object invoke(Object object, String methodName, AbstractObjectSupplier objectSupplier)
			throws InvocationTargetException, CoreException {
		Object result = invokeUsingClass(object, object.getClass(), methodName,
				IInjector.NOT_A_VALUE, objectSupplier);
		if (result == IInjector.NOT_A_VALUE) {
			IStatus status = new Status(IStatus.ERROR, "org.eclipse.e4.core.services",
					"Unable to find matching method to invoke");
			throw new CoreException(status);
		}
		return result;
	}

	public Object invoke(Object object, String methodName, Object defaultValue,
			AbstractObjectSupplier objectSupplier) throws InvocationTargetException {
		return invokeUsingClass(object, object.getClass(), methodName, defaultValue, objectSupplier);
	}

	private Object invokeUsingClass(Object userObject, Class<?> currentClass, String methodName,
			Object defaultValue, AbstractObjectSupplier objectSupplier)
			throws InvocationTargetException {
		Method[] methods = currentClass.getDeclaredMethods();
		for (int j = 0; j < methods.length; j++) {
			Method method = methods[j];
			if (!method.getName().equals(methodName))
				continue;
			MethodRequestor requestor = new MethodRequestor(method, userObject, false, false, true);

			Object[] actualArgs = resolveArgs(requestor, objectSupplier, false);
			int unresolved = unresolved(actualArgs);
			if (unresolved != -1) {
				logError("Injection failed for object \""
						+ requestor.getRequestingObject().toString()
						+ "\". Unable to find value for \""
						+ requestor.getDependentObjects()[unresolved] + "\"");
				return null;
			}
			requestor.setResolvedArgs(actualArgs);

			try {
				return requestor.execute();
			} catch (InstantiationException e) {
				// TBD clean up the error handling; need to propagate original exception
				logError("Exception occured in the injected method " + method.getName(), e);
				return null;
			}
		}
		Class<?> superClass = currentClass.getSuperclass();
		if (superClass == null) {
			return defaultValue;
		}
		return invokeUsingClass(userObject, superClass, methodName, defaultValue, objectSupplier);
	}

	public Object make(Class<?> clazz, AbstractObjectSupplier objectSupplier)
			throws InvocationTargetException, InstantiationException {
		IObjectDescriptor descriptor = ObjectDescriptorFactory.make(clazz, false);
		return make(descriptor, objectSupplier);
	}

	public Object make(IObjectDescriptor descriptor, AbstractObjectSupplier objectSupplier)
			throws InvocationTargetException, InstantiationException {
		IBinding binding = findBinding(descriptor);
		if (binding == null) {
			Class<?> desiredClass = descriptor.getElementClass();
			return internalMake(desiredClass, objectSupplier);
		}
		return internalMake(binding.getImplementationClass(), objectSupplier);
	}

	private Object internalMake(Class<?> clazz, AbstractObjectSupplier objectSupplier)
			throws InvocationTargetException, InstantiationException {

		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
			InjectionProperties cProps = annotationSupport.getInjectProperties(constructor);
			if (!cProps.shouldInject() && constructor.getParameterTypes().length != 0)
				continue;

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

			Object newInstance = requestor.execute();
			if (newInstance != null) {
				inject(newInstance, objectSupplier);
				if (isSingleton) {
					synchronized (singletonCache) { // TBD this is not quite right, synch the method
						singletonCache.put(clazz, newInstance);
					}
				}
				return newInstance;
			}
		}

		logError("Could not find satisfiable constructor in class " + clazz.getName());
		return null;
	}

	public boolean injectStatic(Class<?> clazz, AbstractObjectSupplier objectSupplier) {
		// TBD add processing on a null object
		Object object;
		try {
			object = make(clazz, objectSupplier);
		} catch (InvocationTargetException e) {
			// try-catch won't be necessary once we stop creating an object
			e.printStackTrace();
			return false;
		} catch (InstantiationException e) {
			// try-catch won't be necessary once we stop creating an object
			e.printStackTrace();
			return false;
		}

		// TBD this is copy/paste from as invoke() with static = true.
		// Two stages: first, go and collect {requestor, descriptor[] }
		ArrayList<Requestor> requestors = new ArrayList<Requestor>();
		processClassHierarchy(object, true /* static */, true /* track */, true /* normal order */,
				requestors);
		// Ask suppliers to fill actual values {requestor, descriptor[], actualvalues[] }
		if (!resolveRequestorArgs(requestors, objectSupplier, false))
			return false;

		// Call requestors in order
		for (Requestor requestor : requestors) {
			try {
				requestor.execute();
			} catch (InvocationTargetException e) {
				logError("Injection failed for the object \"" + object.toString()
						+ "\". Unable to execute \"" + requestor.toString() + "\"");
				return false;
			} catch (InstantiationException e) {
				logError("Injection failed for the object \"" + object.toString()
						+ "\". Unable to execute \"" + requestor.toString() + "\"");
				return false;
			}
		}

		return true;
	}

	public boolean update(IRequestor[] requestors, AbstractObjectSupplier objectSupplier) {
		ArrayList<Requestor> list = new ArrayList<Requestor>(requestors.length);
		for (IRequestor requestor : requestors) {
			list.add((Requestor) requestor);
		}
		resolveRequestorArgs(list, objectSupplier, true);

		// Call requestors in order
		for (IRequestor requestor : requestors) {
			try {
				((Requestor) requestor).execute();
			} catch (InvocationTargetException e) {
				logError("Injection failed for the object \""
						+ requestor.getRequestingObject().toString() + "\". Unable to execute \""
						+ requestor.toString() + "\"");
				return false;
			} catch (InstantiationException e) {
				logError("Injection failed for the object \""
						+ requestor.getRequestingObject().toString() + "\". Unable to execute \""
						+ requestor.toString() + "\"");
				return false;
			}
		}
		return true;
	}

	public boolean disposed(AbstractObjectSupplier objectSupplier) {
		List<WeakReference<?>> references = getSupplierObjects(objectSupplier);
		if (references == null)
			return true;
		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++) {
			processPreDestory(objects[i], objects[i].getClass(), new ArrayList<Class<?>>(5));
			uninject(objects[i], objectSupplier);
		}
		forgetSupplier(objectSupplier);
		return true;
	}

	private void processPreDestory(Object userObject, Class<?> objectClass,
			ArrayList<Class<?>> classHierarchy) {
		Class<?> superClass = objectClass.getSuperclass();
		if (superClass != null && !superClass.getName().equals(JAVA_OBJECT)) {
			classHierarchy.add(objectClass);
			processPreDestory(userObject, superClass, classHierarchy);
			classHierarchy.remove(objectClass);
		}
		Method[] methods = objectClass.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			if (method.getParameterTypes().length > 0) // TBD why?
				continue;
			if (!annotationSupport.isPreDestory(method))
				continue;
			if (!isOverridden(method, classHierarchy)) {
				// TBD optional @PreDestory? might make sense if we allow args on those methods
				MethodRequestor requestor = new MethodRequestor(method, userObject, false, false,
						false);
				try {
					requestor.execute();
				} catch (InvocationTargetException e) {
					logError("Unable to call pre-destory method \"" + method.getName() + "\"", e);
				} catch (InstantiationException e) {
					logError("Unable to call pre-destory method \"" + method.getName() + "\"", e);
				}
			}
		}
		if (userObject instanceof IDisposable)
			((IDisposable) userObject).dispose();
	}

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

			if (requestor.isOptional())
				requestor.setResolvedArgs(null);
			else {
				logError("Injection failed for object \""
						+ requestor.getRequestingObject().toString()
						+ "\". Unable to find value for \""
						+ requestor.getDependentObjects()[unresolved] + "\"");
				return false;
			}
		}
		return true;
	}

	private Object[] resolveArgs(Requestor requestor, AbstractObjectSupplier objectSupplier,
			boolean fillNulls) {
		IObjectDescriptor[] descriptors = requestor.getDependentObjects();

		// 0) initial fill - all are unresolved
		Object[] actualArgs = new Object[descriptors.length];
		for (int i = 0; i < actualArgs.length; i++) {
			actualArgs[i] = NOT_A_VALUE;
		}

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

		// 2) use the primary supplier
		if (objectSupplier != null) {
			Object[] primarySupplierArgs = objectSupplier.get(descriptors, requestor);
			for (int i = 0; i < actualArgs.length; i++) {
				if (descriptors[i] == null)
					continue; // already resolved
				if (primarySupplierArgs[i] != NOT_A_VALUE) {
					actualArgs[i] = primarySupplierArgs[i];
					descriptors[i] = null; // mark as used
				}
			}
		}

		// 3) try extended suppliers
		for (int i = 0; i < actualArgs.length; i++) {
			if (descriptors[i] == null)
				continue; // already resolved
			AbstractObjectSupplier extendedSupplier = findExtendedSupplier(descriptors[i]);
			if (extendedSupplier == null)
				continue;
			Object result = extendedSupplier.get(descriptors[i], requestor);
			if (result != NOT_A_VALUE) {
				actualArgs[i] = result;
				descriptors[i] = null; // mark as used
			}
		}

		// 4) try the bindings
		for (int i = 0; i < actualArgs.length; i++) {
			if (descriptors[i] == null)
				continue; // already resolved
			IBinding binding = findBinding(descriptors[i]);
			if (binding != null) {
				try {
					actualArgs[i] = internalMake(binding.getImplementationClass(), objectSupplier);
				} catch (InvocationTargetException e) {
					logError("Unable to create object for class \""
							+ binding.getImplementationClass() + "\".", e);
					continue;
				} catch (InstantiationException e) {
					logError("Unable to create object for class \""
							+ binding.getImplementationClass() + "\".", e);
					continue;
				}
			}
		}

		// 5) post process
		descriptors = requestor.getDependentObjects(); // reset nulled out values
		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 = descriptors[i].getElementClass();
				if (!descriptorsClass.isAssignableFrom(actualArgs[i].getClass()))
					actualArgs[i] = IInjector.NOT_A_VALUE;
			}
			// replace optional unresolved values with null
			if (descriptors[i].isOptional() && actualArgs[i] == IInjector.NOT_A_VALUE)
				actualArgs[i] = null;
			else if (fillNulls && actualArgs[i] == IInjector.NOT_A_VALUE)
				actualArgs[i] = null;
		}

		return actualArgs;
	}

	private AbstractObjectSupplier findExtendedSupplier(IObjectDescriptor descriptor) {
		String[] qualifiers = descriptor.getQualifiers();
		if (qualifiers == null)
			return null;
		for (String qualifier : qualifiers) {
			if (extendedSuppliers.containsKey(qualifier))
				return extendedSuppliers.get(qualifier);
		}
		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, boolean processStatic, boolean track,
			boolean normalOrder, List<Requestor> requestors) {
		processClass(userObject, (userObject == null) ? null : userObject.getClass(),
				new ArrayList<Class<?>>(5), processStatic, track, normalOrder, requestors);
	}

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

	/**
	 * Make the processor visit all declared fields on the given class.
	 */
	private void processFields(Object userObject, Class<?> objectsClass, boolean processStatic,
			boolean track, List<Requestor> requestors) {
		Field[] fields = objectsClass.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			if (Modifier.isStatic(field.getModifiers()) != processStatic)
				continue;

			// XXX limit to "should inject"
			InjectionProperties properties = annotationSupport.getInjectProperties(field);
			// XXX this will be removed on 1.4/1.5 merge
			if (field.getName().startsWith(IContextConstants.INJECTION_PREFIX))
				properties.setInject(true);
			if (!properties.shouldInject())
				continue;

			requestors.add(new FieldRequestor(field, userObject, track, properties.groupUpdates(),
					properties.isOptional()));
		}
	}

	/**
	 * Make the processor visit all declared methods on the given class.
	 * 
	 * @throws InvocationTargetException
	 */
	private void processMethods(final Object userObject, Class<?> objectsClass,
			ArrayList<Class<?>> classHierarchy, boolean processStatic, boolean track,
			List<Requestor> requestors) {
		Method[] methods = objectsClass.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			final Method method = methods[i];
			if (isOverridden(method, classHierarchy))
				continue; // process in the subclass
			if (Modifier.isStatic(method.getModifiers()) != processStatic)
				continue;

			InjectionProperties properties = annotationSupport.getInjectProperties(method);
			if (method.getName().startsWith(IContextConstants.INJECTION_PREFIX))
				properties.setInject(true);

			// replace with @Event("name") qualifier
			// if (properties.getHandlesEvent() != null) {
			// // XXX this is wrong, but it will be removed anyway
			// ObjectDescriptor desc = ObjectDescriptor.make(IEventBroker.class);
			// IEventBroker eventBroker = (IEventBroker) objectProvider.get(desc);
			// eventBroker.subscribe(properties.getHandlesEvent(), null, new EventHandler() {
			// public void handleEvent(Event event) {
			// Object data = event.getProperty(IEventBroker.DATA);
			// boolean wasAccessible = method.isAccessible();
			// if (!wasAccessible) {
			// method.setAccessible(true);
			// }
			// try {
			// method.invoke(userObject, data);
			// } catch (Exception e) {
			// throw new RuntimeException(e);
			// } finally {
			// if (!wasAccessible) {
			// method.setAccessible(false);
			// }
			// }
			// }
			// }, properties.getEventHeadless());
			// continue;
			// }

			if (!properties.shouldInject())
				continue;

			requestors.add(new MethodRequestor(method, userObject, track,
					properties.groupUpdates(), properties.isOptional()));
		}
	}

	/**
	 * 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));

		for (Class<?> subClass : classHierarchy) {
			try {
				subClass.getDeclaredMethod(method.getName(), method.getParameterTypes());
			} catch (SecurityException e) {
				continue;
			} catch (NoSuchMethodException e) {
				continue; // this is the desired outcome
			}
			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 void processPostConstruct(Object userObject, Class<?> objectClass,
			AbstractObjectSupplier objectSupplier, ArrayList<Class<?>> classHierarchy)
			throws InvocationTargetException, InstantiationException {
		Class<?> superClass = objectClass.getSuperclass();
		if (superClass != null && !superClass.getName().equals(JAVA_OBJECT)) {
			classHierarchy.add(objectClass);
			processPostConstruct(userObject, superClass, objectSupplier, classHierarchy);
			classHierarchy.remove(objectClass);
		}
		Method[] methods = objectClass.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			if (!isPostConstruct(method))
				continue;
			if (isOverridden(method, classHierarchy))
				continue;

			MethodRequestor requestor = new MethodRequestor(method, userObject, false, false, false);
			Object[] actualArgs = resolveArgs(requestor, objectSupplier, false);
			int unresolved = unresolved(actualArgs);
			if (unresolved != -1) {
				logError("Injection failed for object \""
						+ requestor.getRequestingObject().toString()
						+ "\". Unable to find value for \""
						+ requestor.getDependentObjects()[unresolved] + "\"");
				continue;
			}
			requestor.setResolvedArgs(actualArgs);

			try {
				requestor.execute();
			} catch (InvocationTargetException e) {
				logError("Unable to call post-construct method \"" + method.getName() + "\"", e);
			} catch (InstantiationException e) {
				logError("Unable to call post-construct method \"" + method.getName() + "\"", e);
			}
		}
	}

	// TBD simplify this: only one non-annotation and one "implements IInitializable"?
	/**
	 * Returns whether the given method is a post-construction process method, as defined by the
	 * class comment of {@link ContextInjectionFactory}.
	 */
	private boolean isPostConstruct(Method method) {
		boolean isPostConstruct = annotationSupport.isPostConstruct(method);
		if (isPostConstruct)
			return true;
		if (!method.getName().equals(IContextConstants.INJECTION_SET_CONTEXT_METHOD))
			return false;
		Class<?>[] parms = method.getParameterTypes();
		if (parms.length == 0)
			return true;
		if (parms.length == 1 && parms[0].equals(IEclipseContext.class))
			return true;
		return false;
	}

	/**
	 * Returns null if not a provider
	 */
	private Class<?> getProviderType(Type type) {
		if (!(type instanceof ParameterizedType))
			return null;
		Type rawType = ((ParameterizedType) type).getRawType();
		if (!(rawType instanceof Class<?>))
			return null;
		boolean isProvider = ((Class<?>) rawType).equals(Provider.class);
		if (!isProvider)
			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) {
		Class<?> clazz = binding.getDescribedClass();
		synchronized (bindings) {
			if (bindings.containsKey(clazz)) {
				Set<IBinding> collection = bindings.get(clazz);
				String desiredQualifierName = binding.getQualifierName();
				for (Iterator<IBinding> i = collection.iterator(); i.hasNext();) {
					IBinding collectionBinding = i.next();
					if (eq(collectionBinding.getQualifierName(), desiredQualifierName)) {
						i.remove();
						break;
					}
				}
				collection.add(binding);
			} else {
				Set<IBinding> collection = new HashSet<IBinding>(1);
				collection.add(binding);
				bindings.put(clazz, collection);
			}
		}
		return binding;
	}

	private IBinding findBinding(IObjectDescriptor descriptor) {
		Class<?> desiredClass = getProviderType(descriptor.getElementType());
		if (desiredClass == null)
			desiredClass = descriptor.getElementClass();
		synchronized (bindings) {
			if (!bindings.containsKey(desiredClass))
				return null;
			Set<IBinding> collection = bindings.get(desiredClass);
			String desiredQualifierName = descriptor.getQualifierValue(Named.class.getName());

			for (Iterator<IBinding> i = collection.iterator(); i.hasNext();) {
				IBinding collectionBinding = i.next();
				if (eq(collectionBinding.getQualifierName(), 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);
	}

	// TBD implement logging
	private void logError(String msg) {
		logError(msg, new InjectionException());
	}

	private void logError(String msg, Throwable e) {
		if (msg != null)
			System.err.println(msg);
		if (e != null)
			e.printStackTrace();
	}

}
