/* gnu.java.beans.IntrospectionIncubator
   Copyright (C) 1998, 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.beans;

import gnu.java.lang.ArrayHelper;
import gnu.java.lang.ClassHelper;

import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 ** IntrospectionIncubator takes in a bunch of Methods, and
 ** Introspects only those Methods you give it.<br/>
 **
 ** See {@link addMethod(Method)} for details which rules apply to
 ** the methods.
 **
 ** @author John Keiser
 ** @author Robert Schuster
 ** @see gnu.java.beans.ExplicitBeanInfo
 ** @see java.beans.BeanInfo
 **/

public class IntrospectionIncubator {
	Hashtable propertyMethods = new Hashtable();
	Hashtable listenerMethods = new Hashtable();
	Vector otherMethods = new Vector();

	Class propertyStopClass;
	Class eventStopClass;
	Class methodStopClass;

	public IntrospectionIncubator() {
	}

	/** Examines the given method and files it in a suitable collection.
	 * It files the method as a property method if it finds:
	 * <lu>
	 * <li>boolean "is" getter</li>
	 * <li>"get" style getter</li>
	 * <li>single argument setter</li>
	 * <li>indiced setter and getter</li> 
	 * </ul>
	 * It files the method as a listener method if all of these rules apply:
	 * <lu>
	 * <li>the method name starts with "add" or "remove"</li>
	 * <li>there is only a single argument</li>
	 * <li>the argument type is a subclass of <code>java.util.EventListener</code></li>
	 * </ul>
	 * All public methods are filed as such. 
	 *   
	 * @param method The method instance to examine.
	 */
	public void addMethod(Method method) {
		if(Modifier.isPublic(method.getModifiers())) {
			String name = ClassHelper.getTruncatedName(method.getName());
			Class retType = method.getReturnType();
			Class[] params = method.getParameterTypes();
			boolean isVoid = retType.equals(java.lang.Void.TYPE);
			Class methodClass = method.getDeclaringClass();
			
			/* Accepts the method for examination if no stop class is given or the method is declared in a subclass of the stop class.
			 * The rules for this are described in {@link java.beans.Introspector.getBeanInfo(Class, Class)}.
			 * This block finds out whether the method is a suitable getter or setter method (or read/write method).  
			 */
			if(isReachable(propertyStopClass, methodClass)) {
				/* At this point a method may regarded as a property's read or write method if its name
				 * starts with "is", "get" or "set". However, if a method is static it cannot be part
				 * of a property.
				 */
				if(Modifier.isStatic(method.getModifiers())) {
					// files method as other because it is static
					otherMethods.addElement(method);
				} else if(name.startsWith("is")
				   && retType.equals(java.lang.Boolean.TYPE)
				   && params.length == 0) {
				   	// files method as boolean "is" style getter
					addToPropertyHash(name,method,IS);
				} else if(name.startsWith("get") && !isVoid) {
					if(params.length == 0) {
						// files as legal non-argument getter
						addToPropertyHash(name,method,GET);
					} else if(params.length == 1 && params[0].equals(java.lang.Integer.TYPE)) {
						// files as legal indiced getter
						addToPropertyHash(name,method,GET_I);
					} else {
						// files as other because the method's signature is not Bean-like
						otherMethods.addElement(method);
					}
				} else if(name.startsWith("set") && isVoid) {
					if(params.length == 1) {
						// files as legal single-argument setter method
						addToPropertyHash(name,method,SET);
					} else if(params.length == 2 && params[0].equals(java.lang.Integer.TYPE)) {
						// files as legal indiced setter method
						addToPropertyHash(name,method,SET_I);
					} else {
						// files as other because the method's signature is not Bean-like
						otherMethods.addElement(method);
					}
				}
			}
			
			if(isReachable(eventStopClass, methodClass)) {
				if(name.startsWith("add")
				          && isVoid
				          && params.length == 1
				          && java.util.EventListener.class.isAssignableFrom(params[0])) {
					addToListenerHash(name,method,ADD);
				} else if(name.startsWith("remove")
				          && isVoid
				          && params.length == 1
				          && java.util.EventListener.class.isAssignableFrom(params[0])) {
					addToListenerHash(name,method,REMOVE);
				}
			}
			 
			if(isReachable(methodStopClass, methodClass)) {
				// files as reachable public method
				otherMethods.addElement(method);
			}
			
		}
	}

	public void addMethods(Method[] m) {
		for(int i=0;i<m.length;i++) {
			addMethod(m[i]);
		}
	}

	public void setPropertyStopClass(Class c) {
		propertyStopClass = c;
	}

	public void setEventStopClass(Class c) {
		eventStopClass = c;
	}

	public void setMethodStopClass(Class c) {
		methodStopClass = c;
	}


	public BeanInfoEmbryo getBeanInfoEmbryo() throws IntrospectionException {
		BeanInfoEmbryo b = new BeanInfoEmbryo();
		findXXX(b,IS);
		findXXXInt(b,GET_I);
		findXXXInt(b,SET_I);
		findXXX(b,GET);
		findXXX(b,SET);
		findAddRemovePairs(b);
		for(int i=0;i<otherMethods.size();i++) {
			MethodDescriptor newMethod = new MethodDescriptor((Method)otherMethods.elementAt(i));
			if(!b.hasMethod(newMethod)) {
				b.addMethod(new MethodDescriptor((Method)otherMethods.elementAt(i)));
			}
		}
		return b;
	}

	public BeanInfo getBeanInfo() throws IntrospectionException {
		return getBeanInfoEmbryo().getBeanInfo();
	}


	void findAddRemovePairs(BeanInfoEmbryo b) throws IntrospectionException {
		Enumeration listenerEnum = listenerMethods.keys();
		while(listenerEnum.hasMoreElements()) {
			DoubleKey k = (DoubleKey)listenerEnum.nextElement();
			Method[] m = (Method[])listenerMethods.get(k);
			if(m[ADD] != null && m[REMOVE] != null) {
				EventSetDescriptor e = new EventSetDescriptor(Introspector.decapitalize(k.getName()),
				                                              k.getType(), k.getType().getMethods(),
				                                              m[ADD],m[REMOVE]);
				e.setUnicast(ArrayHelper.contains(m[ADD].getExceptionTypes(),java.util.TooManyListenersException.class));
				if(!b.hasEvent(e)) {
					b.addEvent(e);
				}
			}
		}
	}

	void findXXX(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
		Enumeration keys = propertyMethods.keys();
		while(keys.hasMoreElements()) {
			DoubleKey k = (DoubleKey)keys.nextElement();
			Method[] m = (Method[])propertyMethods.get(k);
			if(m[funcType] != null) {
				PropertyDescriptor p = new PropertyDescriptor(Introspector.decapitalize(k.getName()),
				                                     m[IS] != null ? m[IS] : m[GET],
				                                     m[SET]);
				if(m[SET] != null) {
					p.setConstrained(ArrayHelper.contains(m[SET].getExceptionTypes(),java.beans.PropertyVetoException.class));
				}
				if(!b.hasProperty(p)) {
					b.addProperty(p);
				}
			}
		}
	}

	void findXXXInt(BeanInfoEmbryo b, int funcType) throws IntrospectionException {
		Enumeration keys = propertyMethods.keys();
		while(keys.hasMoreElements()) {
			DoubleKey k = (DoubleKey)keys.nextElement();
			Method[] m = (Method[])propertyMethods.get(k);
			if(m[funcType] != null) {
				boolean constrained;
				if(m[SET_I] != null) {
					constrained = ArrayHelper.contains(m[SET_I].getExceptionTypes(),java.beans.PropertyVetoException.class);
				} else {
					constrained = false;
				}

				/** Find out if there is an array type get or set **/
				Class arrayType = Array.newInstance(k.getType(),0).getClass();
				DoubleKey findSetArray = new DoubleKey(arrayType,k.getName());
				Method[] m2 = (Method[])propertyMethods.get(findSetArray);
				IndexedPropertyDescriptor p;
				if(m2 == null) {
					p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
				                                          null,null,
				                                          m[GET_I],m[SET_I]);
				} else {
					if(constrained && m2[SET] != null) {
						constrained = ArrayHelper.contains(m2[SET].getExceptionTypes(),java.beans.PropertyVetoException.class);
					}
					p = new IndexedPropertyDescriptor(Introspector.decapitalize(k.getName()),
				                                          m2[GET],m2[SET],
				                                          m[GET_I],m[SET_I]);
				}
				p.setConstrained(constrained);
				if(!b.hasProperty(p)) {
					b.addProperty(p);
				}
			}
		}
	}

	static final int IS=0;
	static final int GET_I=1;
	static final int SET_I=2;
	static final int GET=3;
	static final int SET=4;

	static final int ADD=0;
	static final int REMOVE=1;

	void addToPropertyHash(String name, Method method, int funcType) {
		String newName;
		Class type;

		switch(funcType) {
			case IS:
				type = java.lang.Boolean.TYPE;
				newName = name.substring(2);
				break;
			case GET_I:
				type = method.getReturnType();
				newName = name.substring(3);
				break;
			case SET_I:
				type = method.getParameterTypes()[1];
				newName = name.substring(3);
				break;
			case GET:
				type = method.getReturnType();
				newName = name.substring(3);
				break;
			case SET:
				type = method.getParameterTypes()[0];
				newName = name.substring(3);
				break;
			default:
				return;
		}
		newName = capitalize(newName);

		DoubleKey k = new DoubleKey(type,newName);
		Method[] methods = (Method[])propertyMethods.get(k);
		if(methods == null) {
			methods = new Method[5];
			propertyMethods.put(k,methods);
		}
		methods[funcType] = method;
	}

	void addToListenerHash(String name, Method method, int funcType) {
		String newName;
		Class type;

		switch(funcType) {
			case ADD:
				type = method.getParameterTypes()[0];
				newName = name.substring(3,name.length()-8);
				break;
			case REMOVE:
				type = method.getParameterTypes()[0];
				newName = name.substring(6,name.length()-8);
				break;
			default:
				return;
		}
		newName = capitalize(newName);

		DoubleKey k = new DoubleKey(type,newName);
		Method[] methods = (Method[])listenerMethods.get(k);
		if(methods == null) {
			methods = new Method[2];
			listenerMethods.put(k,methods);
		}
		methods[funcType] = method;
	}

	/* Determines whether <code>stopClass</code> is <code>null</code>
	 * or <code>declaringClass<code> is a true subclass of <code>stopClass</code>.
	 * This expression is useful to detect whether a method should be introspected or not.
	 * The rules for this are described in {@link java.beans.Introspector.getBeanInfo(Class, Class)}.
	 */
	static boolean isReachable(Class stopClass, Class declaringClass) {
		return stopClass == null || (stopClass.isAssignableFrom(declaringClass) && !stopClass.equals(declaringClass));
	}

	/** Transforms a property name into a part of a method name.
	 * E.g. "value" becomes "Value" which can then concatenated with
	 * "set", "get" or "is" to form a valid method name.
	 * 
	 * Implementation notes:
	 * If "" is the argument, it is returned without changes.
	 * If <code>null</code> is the argument, <code>null</code> is returned.
	 * 
	 * @param name Name of a property.
	 * @return Part of a method name of a property.
	 */
	static String capitalize(String name) {
		try {
			if(Character.isUpperCase(name.charAt(0))) {
				return name;
			} else {
				char[] c = name.toCharArray();
				c[0] = Character.toLowerCase(c[0]);
				return new String(c);
			}
		} catch(StringIndexOutOfBoundsException E) {
			return name;
		} catch(NullPointerException E) {
			return null;
		}
	}
}

/** This class is a hashmap key that consists of a <code>Class</code> and a
 * <code>String</code> element.
 * 
 * It is used for XXX: find out what this is used for
 * 
 * @author John Keiser
 * @author Robert Schuster
 */ 
class DoubleKey {
	Class type;
	String name;

	DoubleKey(Class type, String name) {
		this.type = type;
		this.name = name;
	}

	Class getType() {
		return type;
	}

	String getName() {
		return name;
	}

	public boolean equals(Object o) {
		if(o instanceof DoubleKey) {
			DoubleKey d = (DoubleKey)o;
			return d.type.equals(type) && d.name.equals(name);
		} else {
			return false;
		}
	}

	public int hashCode() {
		return type.hashCode() ^ name.hashCode();
	}
}
