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

com.googlecode.openbeans.EventSetDescriptor Maven / Gradle / Ivy

The newest version!
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 com.googlecode.openbeans;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.TooManyListenersException;

import org.apache.harmony.beans.internal.nls.Messages;

public class EventSetDescriptor extends FeatureDescriptor
{
	private Class					listenerType;

	private ArrayList	listenerMethodDescriptors;

	private Method[]					listenerMethods;

	private Method						getListenerMethod;

	private Method						addListenerMethod;

	private Method						removeListenerMethod;

	private boolean						unicast;

	private boolean						inDefaultEventSet	= true;

	public EventSetDescriptor(Class sourceClass, String eventSetName, Class listenerType, String listenerMethodName) throws IntrospectionException
	{
		checkNotNull(sourceClass, eventSetName, listenerType, listenerMethodName);
		setName(eventSetName);
		this.listenerType = listenerType;

		Method method = findListenerMethodByName(listenerMethodName);
		checkEventType(eventSetName, method);
		listenerMethodDescriptors = new ArrayList();
		listenerMethodDescriptors.add(new MethodDescriptor(method));
		addListenerMethod = findMethodByPrefix(sourceClass, "add", ""); //$NON-NLS-1$ //$NON-NLS-2$
		removeListenerMethod = findMethodByPrefix(sourceClass, "remove", ""); //$NON-NLS-1$ //$NON-NLS-2$

		if (addListenerMethod == null || removeListenerMethod == null)
		{
			throw new IntrospectionException(Messages.getString("beans.38")); //$NON-NLS-1$
		}

		getListenerMethod = findMethodByPrefix(sourceClass, "get", "s"); //$NON-NLS-1$ //$NON-NLS-2$
		unicast = isUnicastByDefault(addListenerMethod);
	}

	public EventSetDescriptor(Class sourceClass, String eventSetName, Class listenerType, String[] listenerMethodNames, String addListenerMethodName,
			String removeListenerMethodName) throws IntrospectionException
	{
		this(sourceClass, eventSetName, listenerType, listenerMethodNames, addListenerMethodName, removeListenerMethodName, null);

	}

	public EventSetDescriptor(Class sourceClass, String eventSetName, Class listenerType, String[] listenerMethodNames, String addListenerMethodName,
			String removeListenerMethodName, String getListenerMethodName) throws IntrospectionException
	{

		checkNotNull(sourceClass, eventSetName, listenerType, listenerMethodNames);

		setName(eventSetName);
		this.listenerType = listenerType;

		listenerMethodDescriptors = new ArrayList();
		for (String element : listenerMethodNames)
		{
			Method m = findListenerMethodByName(element);

			// checkEventType(eventSetName, m);
			listenerMethodDescriptors.add(new MethodDescriptor(m));
		}

		if (addListenerMethodName != null)
		{
			this.addListenerMethod = findAddRemoveListenerMethod(sourceClass, addListenerMethodName);
		}
		if (removeListenerMethodName != null)
		{
			this.removeListenerMethod = findAddRemoveListenerMethod(sourceClass, removeListenerMethodName);
		}
		if (getListenerMethodName != null)
		{
			this.getListenerMethod = findGetListenerMethod(sourceClass, getListenerMethodName);
		}
		this.unicast = isUnicastByDefault(addListenerMethod);
	}

	private Method findListenerMethodByName(String listenerMethodName) throws IntrospectionException
	{
		Method result = null;
		Method[] methods = listenerType.getMethods();
		for (Method method : methods)
		{
			if (listenerMethodName.equals(method.getName()))
			{
				Class[] paramTypes = method.getParameterTypes();
				if (paramTypes.length == 1 && paramTypes[0].getName().endsWith("Event")) { //$NON-NLS-1$
					result = method;
					break;
				}

			}
		}
		if (null == result)
		{
			throw new IntrospectionException(Messages.getString("beans.31", //$NON-NLS-1$
					listenerMethodName, listenerType.getName()));
		}
		return result;
	}

	public EventSetDescriptor(String eventSetName, Class listenerType, Method[] listenerMethods, Method addListenerMethod, Method removeListenerMethod)
			throws IntrospectionException
	{

		this(eventSetName, listenerType, listenerMethods, addListenerMethod, removeListenerMethod, null);
	}

	public EventSetDescriptor(String eventSetName, Class listenerType, Method[] listenerMethods, Method addListenerMethod, Method removeListenerMethod,
			Method getListenerMethod) throws IntrospectionException
	{

		setName(eventSetName);
		this.listenerType = listenerType;

		this.listenerMethods = listenerMethods;
		if (listenerMethods != null)
		{
			listenerMethodDescriptors = new ArrayList();

			for (Method element : listenerMethods)
			{
				// XXX do we need this check?
				// checkEventType(eventSetName, element);
				// if (checkMethod(listenerType, element)) {
				this.listenerMethodDescriptors.add(new MethodDescriptor(element));
				// }
			}
		}

		this.addListenerMethod = addListenerMethod;
		this.removeListenerMethod = removeListenerMethod;
		this.getListenerMethod = getListenerMethod;
		this.unicast = isUnicastByDefault(addListenerMethod);
	}

	public EventSetDescriptor(String eventSetName, Class listenerType, MethodDescriptor[] listenerMethodDescriptors, Method addListenerMethod,
			Method removeListenerMethod) throws IntrospectionException
	{

		this(eventSetName, listenerType, null, addListenerMethod, removeListenerMethod, null);

		if (listenerMethodDescriptors != null)
		{
			this.listenerMethodDescriptors = new ArrayList();

			for (MethodDescriptor element : listenerMethodDescriptors)
			{
				this.listenerMethodDescriptors.add(element);
			}
		}
	}

	// ensures that there is no nulls
	@SuppressWarnings("nls")
	private void checkNotNull(Object sourceClass, Object eventSetName, Object alistenerType, Object listenerMethodName)
	{
		if (sourceClass == null)
		{
			throw new NullPointerException(Messages.getString("beans.0C"));
		}
		if (eventSetName == null)
		{
			throw new NullPointerException(Messages.getString("beans.53"));
		}
		if (alistenerType == null)
		{
			throw new NullPointerException(Messages.getString("beans.54"));
		}
		if (listenerMethodName == null)
		{
			throw new NullPointerException(Messages.getString("beans.52"));
		}
	}

	/**
	 * Checks that given listener method has an argument of the valid type.
	 * 
	 * @param eventSetName
	 *            event set name
	 * @param listenerMethod
	 *            listener method
	 * @throws IntrospectionException
	 *             if check fails
	 */
	private static void checkEventType(String eventSetName, Method listenerMethod) throws IntrospectionException
	{
		Class[] params = listenerMethod.getParameterTypes();
		String firstParamTypeName = null;
		String eventTypeName = prepareEventTypeName(eventSetName);

		if (params.length > 0)
		{
			firstParamTypeName = extractShortClassName(params[0].getName());
		}

		if (firstParamTypeName == null || !firstParamTypeName.equals(eventTypeName))
		{
			throw new IntrospectionException(Messages.getString("beans.51", //$NON-NLS-1$
					listenerMethod.getName(), eventTypeName));
		}
	}

	/**
	 * @param fullClassName
	 *            full name of the class
	 * @return name with package and encapsulating class info omitted
	 */
	private static String extractShortClassName(String fullClassName)
	{
		int k = fullClassName.lastIndexOf('$');
		k = (k == -1 ? fullClassName.lastIndexOf('.') : k);
		return fullClassName.substring(k + 1);
	}

	private static String prepareEventTypeName(String eventSetName)
	{
		StringBuilder sb = new StringBuilder();

		if (eventSetName != null && eventSetName.length() > 0)
		{
			sb.append(Character.toUpperCase(eventSetName.charAt(0)));

			if (eventSetName.length() > 1)
			{
				sb.append(eventSetName.substring(1));
			}
		}

		sb.append("Event"); //$NON-NLS-1$
		return sb.toString();
	}

	public Method[] getListenerMethods()
	{
		if (listenerMethods != null)
		{
			return listenerMethods;
		}

		if (listenerMethodDescriptors != null)
		{
			listenerMethods = new Method[listenerMethodDescriptors.size()];
			int index = 0;
			for (MethodDescriptor md : listenerMethodDescriptors)
			{
				listenerMethods[index++] = md.getMethod();
			}
			return listenerMethods;
		}
		return null;
	}

	public MethodDescriptor[] getListenerMethodDescriptors()
	{
		return listenerMethodDescriptors == null ? null : listenerMethodDescriptors.toArray(new MethodDescriptor[0]);
	}

	public Method getRemoveListenerMethod()
	{
		return removeListenerMethod;
	}

	public Method getGetListenerMethod()
	{
		return getListenerMethod;
	}

	public Method getAddListenerMethod()
	{
		return addListenerMethod;
	}

	public Class getListenerType()
	{
		return listenerType;
	}

	public void setUnicast(boolean unicast)
	{
		this.unicast = unicast;
	}

	public void setInDefaultEventSet(boolean inDefaultEventSet)
	{
		this.inDefaultEventSet = inDefaultEventSet;
	}

	public boolean isUnicast()
	{
		return unicast;
	}

	public boolean isInDefaultEventSet()
	{
		return inDefaultEventSet;
	}

	/**
	 * Searches for {add|remove}Listener methods in the event source. Parameter check is also performed.
	 * 
	 * @param sourceClass
	 *            event source class
	 * @param methodName
	 *            method name to search
	 * @return found method
	 * @throws IntrospectionException
	 *             if no valid method found
	 */
	private Method findAddRemoveListenerMethod(Class sourceClass, String methodName) throws IntrospectionException
	{
		try
		{
			return sourceClass.getMethod(methodName, listenerType);
		}
		catch (NoSuchMethodException e)
		{
			return findAddRemoveListnerMethodWithLessCheck(sourceClass, methodName);
		}
		catch (Exception e)
		{
			throw new IntrospectionException(Messages.getString("beans.31", //$NON-NLS-1$
					methodName, listenerType.getName()));
		}
	}

	private Method findAddRemoveListnerMethodWithLessCheck(Class sourceClass, String methodName) throws IntrospectionException
	{
		Method[] methods = sourceClass.getMethods();
		Method result = null;
		for (Method method : methods)
		{
			if (method.getName().equals(methodName))
			{
				Class[] paramTypes = method.getParameterTypes();
				if (paramTypes.length == 1)
				{
					result = method;
					break;
				}
			}
		}
		if (null == result)
		{
			throw new IntrospectionException(Messages.getString("beans.31", //$NON-NLS-1$
					methodName, listenerType.getName()));
		}
		return result;
	}

	/**
	 * @param sourceClass
	 *            class of event source
	 * @param methodName
	 *            name of the custom getListeners() method
	 * @return found Method object for custom getListener or null if nothing is found
	 */
	private Method findGetListenerMethod(Class sourceClass, String methodName)
	{
		try
		{
			return sourceClass.getMethod(methodName);
		}
		catch (Exception e)
		{
			// RI keeps silence here and just returns null
			return null;
		}
	}

	private Method findMethodByPrefix(Class sourceClass, String prefix, String postfix)
	{
		String shortName = listenerType.getName();
		if (listenerType.getPackage() != null)
		{
			shortName = shortName.substring(listenerType.getPackage().getName().length() + 1);
		}
		String methodName = prefix + shortName + postfix;
		try
		{
			if ("get".equals(prefix)) { //$NON-NLS-1$
				return sourceClass.getMethod(methodName);
			}
		}
		catch (NoSuchMethodException nsme)
		{
			return null;
		}
		Method[] methods = sourceClass.getMethods();
		for (int i = 0; i < methods.length; i++)
		{
			if (methods[i].getName().equals(methodName))
			{
				Class[] paramTypes = methods[i].getParameterTypes();
				if (paramTypes.length == 1)
				{
					return methods[i];
				}
			}
		}
		return null;
	}

	private static boolean isUnicastByDefault(Method addMethod)
	{
		if (addMethod != null)
		{
			Class[] exceptionTypes = addMethod.getExceptionTypes();
			for (Class element : exceptionTypes)
			{
				if (element.equals(TooManyListenersException.class))
				{
					return true;
				}
			}
		}
		return false;
	}

	void merge(EventSetDescriptor event)
	{
		super.merge(event);
		if (addListenerMethod == null)
		{
			addListenerMethod = event.addListenerMethod;
		}
		if (getListenerMethod == null)
		{
			getListenerMethod = event.getListenerMethod;
		}
		if (listenerMethodDescriptors == null)
		{
			listenerMethodDescriptors = event.listenerMethodDescriptors;
		}
		if (listenerMethods == null)
		{
			listenerMethods = event.listenerMethods;
		}
		if (listenerType == null)
		{
			listenerType = event.listenerType;
		}

		if (removeListenerMethod == null)
		{
			removeListenerMethod = event.removeListenerMethod;
		}
		inDefaultEventSet &= event.inDefaultEventSet;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy