/*
 * 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 org.apache.wicket.core.util.lang;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.wicket.Application;
import org.apache.wicket.Session;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.core.util.lang.PropertyResolverConverter;
import org.apache.wicket.util.convert.ConversionException;
import org.apache.wicket.util.lang.Generics;
import org.apache.wicket.util.string.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class parses expressions to lookup or set a value on the object that is given. <br/>
 * The supported expressions are:
 * <dl>
 * <dt>"property"</dt>
 * <dd>
 * This could be a bean property with getter and setter. Or if a map is given as
 * an object it will be lookup with the expression as a key when there is not getter for that
 * property.
 * </dd>
 * <dt>"property1.property2"</dt>
 * <dd>
 * Both properties are looked up as described above. If property1 evaluates to
 * null then if there is a setter (or if it is a map) and the Class of the property has a default
 * constructor then the object will be constructed and set on the object.
 * </dd>
 * <dt>"method()"</dt>
 * <dd>
 * The corresponding method is invoked.
 * </dd>
 * <dt>"property.index" or "property[index]"</dt>
 * <dd>
 * If the property is a List or Array then the following expression can be a index on
 * that list like: 'mylist.0'. The list will grow automatically if the index is greater than the size.<p>
 * This expression will also map on indexed properties, i.e. {@code getProperty(index)} and {@code setProperty(index,value)}
 * methods.
 * </dd>
 * <dt>"property.key" or "property[key]"</dt>
 * <dd>
 * If the property is a Map then the following expression can be a key in that map like: 'myMap.key'.
 * </dd>
 * </dl>
 * <strong>Note that the {@link DefaultGetAndSetLocator} by default provides access to private members
 * and methods. If guaranteeing encapsulation of the target objects is a big concern, you should consider
 * using an alternative implementation.</strong>
 * <p>
 * <strong>Note: If a property evaluates to an instance of {@link org.apache.wicket.model.IModel} then
 * the expression should use '.object' to work with its value.</strong>
 *
 * @author jcompagner
 * @author svenmeier
 */
public final class PropertyResolver
{
	/** Log. */
	private static final Logger log = LoggerFactory.getLogger(PropertyResolver.class);

	private final static int RETURN_NULL = 0;
	private final static int CREATE_NEW_VALUE = 1;
	private final static int RESOLVE_CLASS = 2;

	private final static ConcurrentHashMap<Object, IPropertyLocator> applicationToLocators = Generics.newConcurrentHashMap(2);

	private static final String GET = "get";
	private static final String IS = "is";
	private static final String SET = "set";

	/**
	 * Looks up the value from the object with the given expression. If the expression, the object
	 * itself or one property evaluates to null then a null will be returned.
	 *
	 * @param expression
	 *            The expression string with the property to be lookup.
	 * @param object
	 *            The object which is evaluated.
	 * @return The value that is evaluated. Null something in the expression evaluated to null.
	 */
	public static Object getValue(final String expression, final Object object)
	{
		if (expression == null || expression.equals("") || object == null)
		{
			return object;
		}

		ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, RETURN_NULL);
		if (objectWithGetAndSet == null)
		{
			return null;
		}

		return objectWithGetAndSet.getValue();
	}

	/**
	 * Set the value on the object with the given expression. If the expression can't be evaluated
	 * then a WicketRuntimeException will be thrown. If a null object is encountered then it will
	 * try to generate it by calling the default constructor and set it on the object.
	 *
	 * The value will be tried to convert to the right type with the given converter.
	 *
	 * @param expression
	 *            The expression string with the property to be set.
	 * @param object
	 *            The object which is evaluated to set the value on.
	 * @param value
	 *            The value to set.
	 * @param converter
	 *            The converter to convert the value if needed to the right type.
	 * @throws WicketRuntimeException
	 */
	public static void setValue(final String expression, final Object object,
		final Object value, final PropertyResolverConverter converter)
	{
		if (Strings.isEmpty(expression))
		{
			throw new WicketRuntimeException("Empty expression setting value: " + value +
				" on object: " + object);
		}
		if (object == null)
		{
			throw new WicketRuntimeException(
				"Attempted to set property value on a null object. Property expression: " +
					expression + " Value: " + value);
		}

		ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, CREATE_NEW_VALUE);
		if (objectWithGetAndSet == null)
		{
			throw new WicketRuntimeException("Null object returned for expression: " + expression +
				" for setting value: " + value + " on: " + object);
		}
		objectWithGetAndSet.setValue(value, converter == null ? new PropertyResolverConverter(Application.get()
			.getConverterLocator(), Session.get().getLocale()) : converter);
	}

	/**
	 * @param expression
	 * @param object
	 * @return class of the target property object
	 * @throws WicketRuntimeException if the cannot be resolved
	 */
	public static Class<?> getPropertyClass(final String expression, final Object object)
	{
		ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, RESOLVE_CLASS);
		if (objectWithGetAndSet == null)
		{
			throw new WicketRuntimeException("Null object returned for expression: " + expression +
				" for getting the target class of: " + object);
		}
		return objectWithGetAndSet.getTargetClass();
	}

	/**
	 * @param <T>
	 * @param expression
	 * @param clz
	 * @return class of the target Class property expression
	 * @throws WicketRuntimeException if class cannot be resolved
	 */
	@SuppressWarnings("unchecked")
	public static <T> Class<T> getPropertyClass(final String expression, final Class<?> clz)
	{
		ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, null, RESOLVE_CLASS, clz);
		if (objectWithGetAndSet == null)
		{
			throw new WicketRuntimeException("No Class returned for expression: " + expression +
				" for getting the target class of: " + clz);
		}
		return (Class<T>)objectWithGetAndSet.getTargetClass();
	}

	/**
	 * @param expression
	 * @param object
	 * @return Field for the property expression
	 * @throws WicketRuntimeException if there is no such field
	 */
	public static Field getPropertyField(final String expression, final Object object)
	{
		ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, RESOLVE_CLASS);
		if (objectWithGetAndSet == null)
		{
			throw new WicketRuntimeException("Null object returned for expression: " + expression +
				" for getting the target class of: " + object);
		}
		return objectWithGetAndSet.getField();
	}

	/**
	 * @param expression
	 * @param object
	 * @return Getter method for the property expression
	 * @throws WicketRuntimeException if there is no getter method
	 */
	public static Method getPropertyGetter(final String expression, final Object object)
	{
		ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, RESOLVE_CLASS);
		if (objectWithGetAndSet == null)
		{
			throw new WicketRuntimeException("Null object returned for expression: " + expression +
				" for getting the target class of: " + object);
		}
		return objectWithGetAndSet.getGetter();
	}

	/**
	 * @param expression
	 * @param object
	 * @return Setter method for the property expression
	 * @throws WicketRuntimeException if there is no setter method
	 */
	public static Method getPropertySetter(final String expression, final Object object)
	{
		ObjectWithGetAndSet objectWithGetAndSet = getObjectWithGetAndSet(expression, object, RESOLVE_CLASS);
		if (objectWithGetAndSet == null)
		{
			throw new WicketRuntimeException("Null object returned for expression: " + expression +
				" for getting the target class of: " + object);
		}
		return objectWithGetAndSet.getSetter();
	}

	/**
	 * Just delegating the call to the original getObjectAndGetSetter passing the object type as
	 * parameter.
	 *
	 * @param expression
	 * @param object
	 * @param tryToCreateNull
	 * @return {@link ObjectWithGetAndSet}
	 */
	private static ObjectWithGetAndSet getObjectWithGetAndSet(final String expression,
		final Object object, int tryToCreateNull)
	{
		return getObjectWithGetAndSet(expression, object, tryToCreateNull, object.getClass());
	}

	/**
	 * Receives the class parameter also, since this method can resolve the type for some
	 * expression, only knowing the target class
	 *
	 * @param expression
	 * @param object
	 * @param tryToCreateNull
	 * @param clz
	 * @return {@link ObjectWithGetAndSet}
	 */
	private static ObjectWithGetAndSet getObjectWithGetAndSet(final String expression, final Object object, final int tryToCreateNull, Class<?> clz)
	{
		String expressionBracketsSeperated = Strings.replaceAll(expression, "[", ".[").toString();
		int index = getNextDotIndex(expressionBracketsSeperated, 0);
		while (index == 0 && expressionBracketsSeperated.startsWith("."))
		{
			// eat dots at the beginning of the expression since they will confuse
			// later steps
			expressionBracketsSeperated = expressionBracketsSeperated.substring(1);
			index = getNextDotIndex(expressionBracketsSeperated, 0);
		}
		int lastIndex = 0;
		Object value = object;
		String exp = expressionBracketsSeperated;
		while (index != -1)
		{
			exp = expressionBracketsSeperated.substring(lastIndex, index);
			if (exp.length() == 0)
			{
				exp = expressionBracketsSeperated.substring(index + 1);
				break;
			}

			IGetAndSet getAndSet = null;
			try
			{
				getAndSet = getGetAndSet(exp, clz);
			}
			catch (WicketRuntimeException ex)
			{
				// expression by itself can't be found. try combined with the following
				// expression (e.g. for a indexed property);
				int temp = getNextDotIndex(expressionBracketsSeperated, index + 1);
				if (temp == -1)
				{
					exp = expressionBracketsSeperated.substring(lastIndex);
					break;
				} else {
					index = temp;
					continue;
				}
			}
			Object nextValue = null;
			if (value != null)
			{
				nextValue = getAndSet.getValue(value);
			}
			if (nextValue == null)
			{
				if (tryToCreateNull == CREATE_NEW_VALUE)
				{
					nextValue = getAndSet.newValue(value);
					if (nextValue == null)
					{
						return null;
					}
				}
				else if (tryToCreateNull == RESOLVE_CLASS)
				{
					clz = getAndSet.getTargetClass();
				}
				else
				{
					return null;
				}
			}
			value = nextValue;
			if (value != null)
			{
				// value can be null if we are in the RESOLVE_CLASS
				clz = value.getClass();
			}

			lastIndex = index + 1;
			index = getNextDotIndex(expressionBracketsSeperated, lastIndex);
			if (index == -1)
			{
				exp = expressionBracketsSeperated.substring(lastIndex);
				break;
			}
		}
		IGetAndSet getAndSet = getGetAndSet(exp, clz);
		return new ObjectWithGetAndSet(getAndSet, value);
	}

	/**
	 *
	 * @param expression
	 * @param start
	 * @return next dot index
	 */
	private static int getNextDotIndex(final String expression, final int start)
	{
		boolean insideBracket = false;
		for (int i = start; i < expression.length(); i++)
		{
			char ch = expression.charAt(i);
			if (ch == '.' && !insideBracket)
			{
				return i;
			}
			else if (ch == '[')
			{
				insideBracket = true;
			}
			else if (ch == ']')
			{
				insideBracket = false;
			}
		}
		return -1;
	}

	private static IGetAndSet getGetAndSet(String exp, final Class<?> clz)
	{
		IPropertyLocator locator = getLocator();
		
		IGetAndSet getAndSet = locator.get(clz, exp);
		if (getAndSet == null) {
			throw new WicketRuntimeException(
					"Property could not be resolved for class: " + clz + " expression: " + exp);
		}
		
		return getAndSet;
	}

	/**
	 * Utility class: instantiation not allowed.
	 */
	private PropertyResolver()
	{
	}

	/**
	 * @author jcompagner
	 *
	 */
	private final static class ObjectWithGetAndSet
	{
		private final IGetAndSet getAndSet;
		private final Object value;

		/**
		 * @param getAndSet
		 * @param value
		 */
		public ObjectWithGetAndSet(IGetAndSet getAndSet, Object value)
		{
			this.getAndSet = getAndSet;
			this.value = value;
		}

		/**
		 * @param value
		 * @param converter
		 */
		public void setValue(Object value, PropertyResolverConverter converter)
		{
			getAndSet.setValue(this.value, value, converter);
		}

		/**
		 * @return The value
		 */
		public Object getValue()
		{
			return getAndSet.getValue(value);
		}

		/**
		 * @return class of property value
		 */
		public Class<?> getTargetClass()
		{
			return getAndSet.getTargetClass();
		}

		/**
		 * @return Field or null if no field exists for expression
		 */
		public Field getField()
		{
			return getAndSet.getField();
		}

		/**
		 * @return Getter method or null if no getter exists for expression
		 */
		public Method getGetter()
		{
			return getAndSet.getGetter();
		}

		/**
		 * @return Setter method or null if no setter exists for expression
		 */
		public Method getSetter()
		{
			return getAndSet.getSetter();
		}
	}

	/**
	 * @author jcompagner
	 */
	public interface IGetAndSet
	{
		/**
		 * @param object
		 *            The object where the value must be taken from.
		 *
		 * @return The value of this property
		 */
		public Object getValue(final Object object);

		/**
		 * @return The target class of the object that as to be set.
		 */
		public Class<?> getTargetClass();

		/**
		 * @param object
		 *            The object where the new value must be set on.
		 *
		 * @return The new value for the property that is set back on that object.
		 */
		public Object newValue(Object object);

		/**
		 * @param object
		 * @param value
		 * @param converter
		 */
		public void setValue(final Object object, final Object value,
			PropertyResolverConverter converter);

		/**
		 * @return Field or null if there is no field
		 */
		public Field getField();

		/**
		 * @return Getter method or null if there is no getter
		 */
		public Method getGetter();

		/**
		 * @return Setter of null if there is no setter
		 */
		public Method getSetter();
	}

	public static abstract class AbstractGetAndSet implements IGetAndSet
	{
		/**
		 * {@inheritDoc}
		 */
		@Override
		public Field getField()
		{
			return null;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Method getGetter()
		{
			return null;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Method getSetter()
		{
			return null;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Class<?> getTargetClass()
		{
			return null;
		}
	}

	private static final class MapGetAndSet extends AbstractGetAndSet
	{
		private final String key;

		MapGetAndSet(String key)
		{
			this.key = key;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object getValue(final Object object)
		{
			return ((Map<?, ?>)object).get(key);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		@SuppressWarnings("unchecked")
		public void setValue(final Object object, final Object value,
			final PropertyResolverConverter converter)
		{
			((Map<String, Object>)object).put(key, value);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object newValue(final Object object)
		{
			// Map can't make a newValue or should it look what is more in the
			// map and try to make one of the class if finds?
			return null;
		}
	}

	private static final class ListGetAndSet extends AbstractGetAndSet
	{
		final private int index;

		ListGetAndSet(int index)
		{
			this.index = index;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object getValue(final Object object)
		{
			if (((List<?>)object).size() <= index)
			{
				return null;
			}
			return ((List<?>)object).get(index);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		@SuppressWarnings("unchecked")
		public void setValue(final Object object, final Object value,
			final PropertyResolverConverter converter)
		{
			List<Object> lst = (List<Object>)object;

			if (lst.size() > index)
			{
				lst.set(index, value);
			}
			else if (lst.size() == index)
			{
				lst.add(value);
			}
			else
			{
				while (lst.size() < index)
				{
					lst.add(null);
				}
				lst.add(value);
			}
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object newValue(Object object)
		{
			// List can't make a newValue or should it look what is more in the
			// list and try to make one of the class if finds?
			return null;
		}
	}

	private static final class ArrayGetAndSet extends AbstractGetAndSet
	{
		private final int index;
		private final Class<?> clzComponentType;

		ArrayGetAndSet(Class<?> clzComponentType, int index)
		{
			this.clzComponentType = clzComponentType;
			this.index = index;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object getValue(Object object)
		{
			if (Array.getLength(object) > index)
			{
				return Array.get(object, index);
			}
			return null;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void setValue(Object object, Object value, PropertyResolverConverter converter)
		{
			value = converter.convert(value, clzComponentType);
			Array.set(object, index, value);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object newValue(Object object)
		{
			Object value = null;
			try
			{
				value = clzComponentType.newInstance();
				Array.set(object, index, value);
			}
			catch (Exception e)
			{
				log.warn("Cannot set new value " + value + " at index " + index +
					" for array holding elements of class " + clzComponentType, e);
			}
			return value;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Class<?> getTargetClass()
		{
			return clzComponentType;
		}
	}

	private static final class ArrayLengthGetAndSet extends AbstractGetAndSet
	{
		ArrayLengthGetAndSet()
		{
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object getValue(final Object object)
		{
			return Array.getLength(object);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void setValue(final Object object, final Object value,
			final PropertyResolverConverter converter)
		{
			throw new WicketRuntimeException("You can't set the length on an array:" + object);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object newValue(final Object object)
		{
			throw new WicketRuntimeException("Can't get a new value from a length of an array: " +
				object);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Class<?> getTargetClass()
		{
			return int.class;
		}
	}

	private static final class IndexedPropertyGetAndSet extends AbstractGetAndSet
	{
		final private Integer index;
		final private Method getMethod;
		private Method setMethod;

		IndexedPropertyGetAndSet(final Method method, final int index)
		{
			this.index = index;
			getMethod = method;
			getMethod.setAccessible(true);
		}

		private static Method findSetter(final Method getMethod, final Class<?> clz)
		{
			String name = getMethod.getName();
			name = SET + name.substring(3);
			try
			{
				return clz.getMethod(name, new Class[] { int.class, getMethod.getReturnType() });
			}
			catch (Exception e)
			{
				log.debug("Can't find setter method corresponding to " + getMethod);
			}
			return null;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object getValue(Object object)
		{
			Object ret;
			try
			{
				ret = getMethod.invoke(object, index);
			}
			catch (InvocationTargetException ex)
			{
				throw new WicketRuntimeException("Error calling index property method: " +
					getMethod + " on object: " + object, ex.getCause());
			}
			catch (Exception ex)
			{
				throw new WicketRuntimeException("Error calling index property method: " +
					getMethod + " on object: " + object, ex);
			}
			return ret;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void setValue(final Object object, final Object value,
			final PropertyResolverConverter converter)
		{
			if (setMethod == null)
			{
				setMethod = findSetter(getMethod, object.getClass());
			}
			if (setMethod != null)
			{
				setMethod.setAccessible(true);
				Object converted = converter.convert(value, getMethod.getReturnType());
				if (converted == null && value != null)
				{
					throw new ConversionException("Can't convert value: " + value + " to class: " +
						getMethod.getReturnType() + " for setting it on " + object);
				}
				try
				{
					setMethod.invoke(object, index, converted);
				}
				catch (InvocationTargetException ex)
				{
					throw new WicketRuntimeException("Error index property calling method: " +
						setMethod + " on object: " + object, ex.getCause());
				}
				catch (Exception ex)
				{
					throw new WicketRuntimeException("Error index property calling method: " +
						setMethod + " on object: " + object, ex);
				}
			}
			else
			{
				throw new WicketRuntimeException("No set method defined for value: " + value +
					" on object: " + object);
			}
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Class<?> getTargetClass()
		{
			return getMethod.getReturnType();
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object newValue(Object object)
		{
			if (setMethod == null)
			{
				setMethod = findSetter(getMethod, object.getClass());
			}

			if (setMethod == null)
			{
				log.warn("Null setMethod");
				return null;
			}

			Class<?> clz = getMethod.getReturnType();
			Object value = null;
			try
			{
				value = clz.newInstance();
				setMethod.invoke(object, index, value);
			}
			catch (Exception e)
			{
				log.warn("Cannot set new value " + value + " at index " + index, e);
			}
			return value;
		}
	}

	private static final class MethodGetAndSet extends AbstractGetAndSet
	{
		private final Method getMethod;
		private final Method setMethod;
		private final Field field;

		MethodGetAndSet(Method getMethod, Method setMethod, Field field)
		{
			this.getMethod = getMethod;
			this.getMethod.setAccessible(true);
			this.field = field;
			this.setMethod = setMethod;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public final Object getValue(final Object object)
		{
			Object ret;
			try
			{
				ret = getMethod.invoke(object, (Object[])null);
			}
			catch (InvocationTargetException ex)
			{
				throw new WicketRuntimeException("Error calling method: " + getMethod +
					" on object: " + object, ex.getCause());
			}
			catch (Exception ex)
			{
				throw new WicketRuntimeException("Error calling method: " + getMethod +
					" on object: " + object, ex);
			}
			return ret;
		}

		/**
		 * @param object
		 * @param value
		 * @param converter
		 */
		@Override
		public final void setValue(final Object object, final Object value,
			PropertyResolverConverter converter)
		{
			Class<?> type = null;
			if (setMethod != null)
			{
				// getMethod is always there and if the value will be set through a setMethod then
				// the getMethod return type will be its type. Else we have to look at the
				// parameters if the setter but getting the return type is quicker
				type = getMethod.getReturnType();
			}
			else if (field != null)
			{
				type = field.getType();
			}

			Object converted = null;
			if (type != null)
			{
				converted = converter.convert(value, type);
				if (converted == null)
				{
					if (value != null)
					{
						throw new ConversionException("Method [" + getMethod +
							"]. Can't convert value: " + value + " to class: " +
							getMethod.getReturnType() + " for setting it on " + object);
					}
					else if (getMethod.getReturnType().isPrimitive())
					{
						throw new ConversionException("Method [" + getMethod +
							"]. Can't convert null value to a primitive class: " +
							getMethod.getReturnType() + " for setting it on " + object);
					}
				}
			}

			if (setMethod != null)
			{
				try
				{
					setMethod.invoke(object, converted);
				}
				catch (InvocationTargetException ex)
				{
					throw new WicketRuntimeException("Error calling method: " + setMethod +
						" on object: " + object, ex.getCause());
				}
				catch (Exception ex)
				{
					throw new WicketRuntimeException("Error calling method: " + setMethod +
						" on object: " + object, ex);
				}
			}
			else if (field != null)
			{
				try
				{
					field.set(object, converted);
				}
				catch (Exception ex)
				{
					throw new WicketRuntimeException("Error setting field: " + field +
						" on object: " + object, ex);
				}
			}
			else
			{
				throw new WicketRuntimeException("no set method defined for value: " + value +
					" on object: " + object + " while respective getMethod being " +
					getMethod.getName());
			}
		}

		private static Method findSetter(Method getMethod, Class<?> clz)
		{
			String name = getMethod.getName();
			if (name.startsWith(GET))
			{
				name = SET + name.substring(3);
			}
			else
			{
				name = SET + name.substring(2);
			}
			try
			{
				Method method = clz.getMethod(name, new Class[] { getMethod.getReturnType() });
				if (method != null)
				{
					method.setAccessible(true);
				}
				return method;
			}
			catch (NoSuchMethodException e)
			{
				Method[] methods = clz.getMethods();
				for (Method method : methods)
				{
					if (method.getName().equals(name))
					{
						Class<?>[] parameterTypes = method.getParameterTypes();
						if (parameterTypes.length == 1)
						{
							if (parameterTypes[0].isAssignableFrom(getMethod.getReturnType()))
							{
								return method;
							}
						}
					}
				}
				log.debug("Cannot find setter corresponding to " + getMethod);
			}
			catch (Exception e)
			{
				log.debug("Cannot find setter corresponding to " + getMethod);
			}
			return null;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object newValue(Object object)
		{
			if (setMethod == null)
			{
				log.warn("Null setMethod");
				return null;
			}

			Class<?> clz = getMethod.getReturnType();
			Object value = null;
			try
			{
				value = clz.newInstance();
				setMethod.invoke(object, value);
			}
			catch (Exception e)
			{
				log.warn("Cannot set new value " + value, e);
			}
			return value;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Class<?> getTargetClass()
		{
			return getMethod.getReturnType();
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Method getGetter()
		{
			return getMethod;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Method getSetter()
		{
			return setMethod;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Field getField()
		{
			return field;
		}
	}

	/**
	 * @author jcompagner
	 */
	private static class FieldGetAndSet extends AbstractGetAndSet
	{
		private final Field field;

		/**
		 * Construct.
		 *
		 * @param field
		 */
		public FieldGetAndSet(final Field field)
		{
			super();
			this.field = field;
			this.field.setAccessible(true);
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object getValue(final Object object)
		{
			try
			{
				return field.get(object);
			}
			catch (Exception ex)
			{
				throw new WicketRuntimeException("Error getting field value of field " + field +
					" from object " + object, ex);
			}
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Object newValue(final Object object)
		{
			Class<?> clz = field.getType();
			Object value = null;
			try
			{
				value = clz.newInstance();
				field.set(object, value);
			}
			catch (Exception e)
			{
				log.warn("Cannot set field " + field + " to " + value, e);
			}
			return value;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void setValue(final Object object, Object value,
			final PropertyResolverConverter converter)
		{
			value = converter.convert(value, field.getType());
			try
			{
				field.set(object, value);
			}
			catch (Exception ex)
			{
				throw new WicketRuntimeException("Error setting field value of field " + field +
					" on object " + object + ", value " + value, ex);
			}
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Class<?> getTargetClass()
		{
			return field.getType();
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public Field getField()
		{
			return field;
		}
	}

	/**
	 * Clean up cache for this app.
	 *
	 * @param application
	 */
	public static void destroy(Application application)
	{
		applicationToLocators.remove(application);
	}

	/**
	 * Sets the {@link IPropertyLocator} for the given application.
	 *
	 * If the Application is null then it will be the default if no application is found. So if you
	 * want to be sure that your {@link IPropertyLocator} is handled in all situations then call this
	 * method twice with your implementations. One time for the application and the second time with
	 * null.
	 *
	 * @param application
	 *            to use or null if the default must be set.
	 * @param classCache
	 */
	@Deprecated
	public static void setClassCache(final Application application, final IClassCache classCache)
	{
		setLocator(application, new IPropertyLocator() {
			
			private DefaultGetAndSetLocator locator = new DefaultGetAndSetLocator();
			
			@Override
			public IGetAndSet get(Class<?> clz, String name) {
				Map<String, IGetAndSet> map = classCache.get(clz);
				if (map == null) {
					map = new ConcurrentHashMap<String, IGetAndSet>(8);
					classCache.put(clz, map);
				}
				
				IGetAndSet getAndSetter = map.get(name);
				if (getAndSetter == null) {
					getAndSetter = locator.get(clz, name);
					map.put(name, getAndSetter);
				}
				
				return getAndSetter;
			}
		});
	}

	/**
	 * Get the current {@link IPropertyLocator}.
	 * 
	 * @return locator for the current {@link Application} or a general one if no current application is present
	 * @see Application#get()
	 */
	public static IPropertyLocator getLocator()
	{
		Object key;
		if (Application.exists())
		{
			key = Application.get();
		}
		else
		{
			key = PropertyResolver.class;
		}
		IPropertyLocator result = applicationToLocators.get(key);
		if (result == null)
		{
			IPropertyLocator tmpResult = applicationToLocators.putIfAbsent(key, result = new CachingGetAndSetLocator(new DefaultGetAndSetLocator()));
			if (tmpResult != null)
			{
				result = tmpResult;
			}
		}
		return result;
	}

	/**
	 * Set a locator for the given application.
	 * 
	 * @param application application, may be {@code null}
	 * @param locator locator
	 */
	public static void setLocator(final Application application, final IPropertyLocator locator)
	{
		if (application == null)
		{
			applicationToLocators.put(PropertyResolver.class, locator);
		}
		else
		{
			applicationToLocators.put(application, locator);
		}
	}

	/**
	 * Specify an {@link IPropertyLocator} instead.
	 */
	@Deprecated
	public static interface IClassCache
	{
		/**
		 * Put the class into the cache, or if that class shouldn't be cached do nothing.
		 *
		 * @param clz
		 * @param values
		 */
		void put(Class<?> clz, Map<String, IGetAndSet> values);

		/**
		 * Returns the class map from the cache.
		 *
		 * @param clz
		 * @return the map of the given class
		 */
		Map<String, IGetAndSet> get(Class<?> clz);
	}

	/**
	 * A locator of properties.
	 * 
	 * @see https://issues.apache.org/jira/browse/WICKET-5623
	 */
	public static interface IPropertyLocator
	{
		/**
		 * Get {@link IGetAndSet} for a property.
		 * 
		 * @param clz owning class
		 * @param exp identifying the property
		 * @return getAndSet or {@code null} if non located
		 */
		IGetAndSet get(Class<?> clz, String exp);
	}

	public static class CachingGetAndSetLocator implements IPropertyLocator
	{
		private final ConcurrentHashMap<String, IGetAndSet> map = Generics.newConcurrentHashMap(16);
		
		/**
		 * Special token to put into the cache representing no located {@link IGetAndSet}. 
		 */
		private IGetAndSet NONE = new AbstractGetAndSet() {

			@Override
			public Object getValue(Object object) {
				return null;
			}

			@Override
			public Object newValue(Object object) {
				return null;
			}

			@Override
			public void setValue(Object object, Object value, PropertyResolverConverter converter) {
			}
		};

		private IPropertyLocator locator;

		public CachingGetAndSetLocator(IPropertyLocator locator) {
			this.locator = locator;
		}

		@Override
		public IGetAndSet get(Class<?> clz, String exp) {
			String key = clz.getName() + "#" + exp;
			
			IGetAndSet located = map.get(key);
			if (located == null) {
				located = locator.get(clz, exp);
				if (located == null) {
					located = NONE;
				}
				map.put(key, located);
			}
			
			if (located == NONE) {
				located = null;
			}
			
			return located;
		}
	}

	/**
	 * Default implementation supporting <em>Java Beans</em> properties, maps, lists and method invocations.
	 */
	public static class DefaultGetAndSetLocator implements IPropertyLocator
	{
		@Override
		public IGetAndSet get(Class<?> clz, String exp) {
			IGetAndSet getAndSet = null;
			
			Method method = null;
			Field field;
			if (exp.startsWith("["))
			{
				// if expression begins with [ skip method finding and use it as
				// a key/index lookup on a map.
				exp = exp.substring(1, exp.length() - 1);
			}
			else if (exp.endsWith("()"))
			{
				// if expression ends with (), don't test for setters just skip
				// directly to method finding.
				method = findMethod(clz, exp);
			}
			else
			{
				method = findGetter(clz, exp);
			}
			if (method == null)
			{
				if (List.class.isAssignableFrom(clz))
				{
					try
					{
						int index = Integer.parseInt(exp);
						getAndSet = new ListGetAndSet(index);
					}
					catch (NumberFormatException ex)
					{
						// can't parse the exp as an index, maybe the exp was a
						// method.
						method = findMethod(clz, exp);
						if (method != null)
						{
							getAndSet = new MethodGetAndSet(method, MethodGetAndSet.findSetter(
								method, clz), null);
						}
						else
						{
							field = findField(clz, exp);
							if (field != null)
							{
								getAndSet = new FieldGetAndSet(field);
							}
							else
							{
								throw new WicketRuntimeException(
									"The expression '" +
										exp +
										"' is neither an index nor is it a method or field for the list " +
										clz);
							}
						}
					}
				}
				else if (Map.class.isAssignableFrom(clz))
				{
					getAndSet = new MapGetAndSet(exp);
				}
				else if (clz.isArray())
				{
					try
					{
						int index = Integer.parseInt(exp);
						getAndSet = new ArrayGetAndSet(clz.getComponentType(), index);
					}
					catch (NumberFormatException ex)
					{
						if (exp.equals("length") || exp.equals("size"))
						{
							getAndSet = new ArrayLengthGetAndSet();
						}
						else
						{
							throw new WicketRuntimeException("Can't parse the expression '" + exp +
								"' as an index for an array lookup");
						}
					}
				}
				else
				{
					field = findField(clz, exp);
					if (field == null)
					{
						method = findMethod(clz, exp);
						if (method == null)
						{
							int index = exp.indexOf('.');
							if (index != -1)
							{
								String propertyName = exp.substring(0, index);
								String propertyIndex = exp.substring(index + 1);
								try
								{
									int parsedIndex = Integer.parseInt(propertyIndex);
									// if so then it could be a getPropertyIndex(int)
									// and setPropertyIndex(int, object)
									String name = Character.toUpperCase(propertyName.charAt(0)) +
										propertyName.substring(1);
									method = clz.getMethod(GET + name, new Class[] { int.class });
									getAndSet = new IndexedPropertyGetAndSet(method, parsedIndex);
								}
								catch (Exception e)
								{
									throw new WicketRuntimeException(
										"No get method defined for class: " + clz +
											" expression: " + propertyName);
								}
							}
						}
						else
						{
							getAndSet = new MethodGetAndSet(method, MethodGetAndSet.findSetter(
								method, clz), null);
						}
					}
					else
					{
						getAndSet = new FieldGetAndSet(field);
					}
				}
			}
			else
			{
				field = findField(clz, exp);
				getAndSet = new MethodGetAndSet(method, MethodGetAndSet.findSetter(method, clz),
					field);
			}
			
			return getAndSet;
		}
		
		/**
		 * @param clz
		 * @param expression
		 * @return introspected field
		 */
		private Field findField(final Class<?> clz, final String expression)
		{
			Field field = null;
			try
			{
				field = clz.getField(expression);
			}
			catch (Exception e)
			{
				Class<?> tmp = clz;
				while (tmp != null && tmp != Object.class)
				{
					Field[] fields = tmp.getDeclaredFields();
					for (Field aField : fields)
					{
						if (aField.getName().equals(expression))
						{
							aField.setAccessible(true);
							return aField;
						}
					}
					tmp = tmp.getSuperclass();
				}
				log.debug("Cannot find field " + clz + "." + expression);
			}
			return field;
		}

		/**
		 * @param clz
		 * @param expression
		 * @return The method for the expression null if not found
		 */
		private Method findGetter(final Class<?> clz, final String expression)
		{
			String name = Character.toUpperCase(expression.charAt(0)) + expression.substring(1);
			Method method = null;
			try
			{
				method = clz.getMethod(GET + name, (Class[])null);
			}
			catch (Exception ignored)
			{
			}
			if (method == null)
			{
				try
				{
					method = clz.getMethod(IS + name, (Class[])null);
				}
				catch (Exception e)
				{
					log.debug("Cannot find getter " + clz + "." + expression);
				}
			}
			return method;
		}

		private Method findMethod(final Class<?> clz, String expression)
		{
			if (expression.endsWith("()"))
			{
				expression = expression.substring(0, expression.length() - 2);
			}
			Method method = null;
			try
			{
				method = clz.getMethod(expression, (Class[])null);
			}
			catch (Exception e)
			{
				log.debug("Cannot find method " + clz + "." + expression);
			}
			return method;
		}
	}
}