// ***************************************************************************************************************************
// * 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.juneau;

import static org.apache.juneau.internal.ArrayUtils.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;
import static org.apache.juneau.internal.StringUtils.*;

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.net.*;
import java.net.URI;
import java.util.*;

import org.apache.juneau.annotation.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.reflect.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.transform.*;
import org.apache.juneau.transforms.*;

/**
 * Contains metadata about a bean property.
 *
 * <p>
 * Contains information such as type of property (e.g. field/getter/setter), class type of property value, and whether
 * any transforms are associated with this property.
 *
 * <p>
 * Developers will typically not need access to this class.  The information provided by it is already exposed through
 * several methods on the {@link BeanMap} API.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public final class BeanPropertyMeta {

	final BeanMeta<?> beanMeta;                               // The bean that this property belongs to.
	private final BeanContext beanContext;                    // The context that created this meta.

	private final String name;                                // The name of the property.
	private final Field field;                                // The bean property field (if it has one).
	private final Field innerField;                                // The bean property field (if it has one).
	private final Method getter, setter, extraKeys;           // The bean property getter and setter.
	private final MethodInfo getterInfo, setterInfo, extraKeysInfo;           // The bean property getter and setter.
	private final boolean isUri;                              // True if this is a URL/URI or annotated with @URI.
	private final boolean isDyna, isDynaGetterMap;            // This is a dyna property (i.e. name="*")

	private final ClassMeta<?>
		rawTypeMeta,                                           // The real class type of the bean property.
		typeMeta;                                              // The transformed class type of the bean property.

	private final String[] properties;                        // The value of the @Beanp(properties) annotation.
	private final PojoSwap swap;                              // PojoSwap defined only via @Beanp annotation.

	private final BeanRegistry beanRegistry;

	private final Object overrideValue;                       // The bean property value (if it's an overridden delegate).
	private final BeanPropertyMeta delegateFor;               // The bean property that this meta is a delegate for.
	private final boolean canRead, canWrite, readOnly, writeOnly;
	private final int hashCode;

	/**
	 * Creates a builder for {@link #BeanPropertyMeta} objects.
	 *
	 * @param beanMeta The metadata on the bean
	 * @param name The bean property name.
	 * @return A new builder.
	 */
	public static Builder builder(BeanMeta<?> beanMeta, String name) {
		return new Builder(beanMeta, name);
	}

	/**
	 * BeanPropertyMeta builder class.
	 */
	public static final class Builder {
		BeanMeta<?> beanMeta;
		BeanContext beanContext;
		String name;
		Field field, innerField;
		Method getter, setter, extraKeys;
		boolean isConstructorArg, isUri, isDyna, isDynaGetterMap;
		ClassMeta<?> rawTypeMeta, typeMeta;
		String[] properties;
		PojoSwap swap;
		BeanRegistry beanRegistry;
		Object overrideValue;
		BeanPropertyMeta delegateFor;
		boolean canRead, canWrite, readOnly, writeOnly;

		Builder(BeanMeta<?> beanMeta, String name) {
			this.beanMeta = beanMeta;
			this.beanContext = beanMeta.ctx;
			this.name = name;
		}

		/**
		 * Sets the raw metadata type for this bean property.
		 *
		 * @param rawMetaType The raw metadata type for this bean property.
		 * @return This object (for method chaining().
		 */
		public Builder rawMetaType(ClassMeta<?> rawMetaType) {
			this.rawTypeMeta = rawMetaType;
			this.typeMeta = rawTypeMeta;
			return this;
		}

		/**
		 * Sets the bean registry to use with this bean property.
		 *
		 * @param beanRegistry The bean registry to use with this bean property.
		 * @return This object (for method chaining().
		 */
		public Builder beanRegistry(BeanRegistry beanRegistry) {
			this.beanRegistry = beanRegistry;
			return this;
		}

		/**
		 * Sets the overridden value of this bean property.
		 *
		 * @param overrideValue The overridden value of this bean property.
		 * @return This object (for method chaining().
		 */
		public Builder overrideValue(Object overrideValue) {
			this.overrideValue = overrideValue;
			return this;
		}

		/**
		 * Sets the original bean property that this one is overriding.
		 *
		 * @param delegateFor The original bean property that this one is overriding.
		 * @return This object (for method chaining().
		 */
		public Builder delegateFor(BeanPropertyMeta delegateFor) {
			this.delegateFor = delegateFor;
			return this;
		}

		Builder canRead() {
			this.canRead = true;
			return this;
		}

		Builder canWrite() {
			this.canWrite = true;
			return this;
		}

		@SuppressWarnings("deprecation")
		boolean validate(BeanContext f, BeanRegistry parentBeanRegistry, Map<Class<?>,Class<?>[]> typeVarImpls, Set<String> bpro, Set<String> bpwo) throws Exception {

			List<Class<?>> bdClasses = new ArrayList<>();

			if (field == null && getter == null && setter == null)
				return false;

			if (field == null && setter == null && f.isBeansRequireSettersForGetters() && ! isConstructorArg)
				return false;

			canRead |= (field != null || getter != null);
			canWrite |= (field != null || setter != null);

			if (innerField != null) {
				BeanProperty px = innerField.getAnnotation(BeanProperty.class);
				Beanp p = innerField.getAnnotation(Beanp.class);
				if (field != null || px != null || p != null) {
					// Only use field type if it's a bean property or has @Beanp annotation.
					// Otherwise, we want to infer the type from the getter or setter.
					rawTypeMeta = f.resolveClassMeta(px, p, innerField.getGenericType(), typeVarImpls);
					isUri |= (rawTypeMeta.isUri());
				}
				if (px != null) {
					if (! px.properties().isEmpty())
						properties = split(px.properties());
					bdClasses.addAll(Arrays.asList(px.beanDictionary()));
				}
				if (p != null) {
					if (! p.bpi().isEmpty())
						properties = split(p.bpi());
					bdClasses.addAll(Arrays.asList(p.dictionary()));
					if (! p.ro().isEmpty())
						readOnly = Boolean.valueOf(p.ro());
					if (! p.wo().isEmpty())
						writeOnly = Boolean.valueOf(p.wo());
				}
				Swap s = innerField.getAnnotation(Swap.class);
				if (s != null) {
					swap = getPropertyPojoSwap(s);
				}
				isUri |= innerField.isAnnotationPresent(org.apache.juneau.annotation.URI.class);
			}

			if (getter != null) {
				BeanProperty px = MethodInfo.of(getter).getAnnotation(BeanProperty.class);
				Beanp p = MethodInfo.of(getter).getAnnotation(Beanp.class);
				if (rawTypeMeta == null)
					rawTypeMeta = f.resolveClassMeta(px, p, getter.getGenericReturnType(), typeVarImpls);
				isUri |= (rawTypeMeta.isUri() || getter.isAnnotationPresent(org.apache.juneau.annotation.URI.class));
				if (px != null) {
					if (properties != null && ! px.properties().isEmpty())
						properties = split(px.properties());
					bdClasses.addAll(Arrays.asList(px.beanDictionary()));
				}
				if (p != null) {
					if (properties != null && ! p.bpi().isEmpty())
						properties = split(p.bpi());
					bdClasses.addAll(Arrays.asList(p.dictionary()));
					if (! p.ro().isEmpty())
						readOnly = Boolean.valueOf(p.ro());
					if (! p.wo().isEmpty())
						writeOnly = Boolean.valueOf(p.wo());
				}
				Swap s = getter.getAnnotation(Swap.class);
				if (s != null && swap == null) {
					swap = getPropertyPojoSwap(s);
				}
			}

			if (setter != null) {
				BeanProperty px = MethodInfo.of(setter).getAnnotation(BeanProperty.class);
				Beanp p = MethodInfo.of(setter).getAnnotation(Beanp.class);
				if (rawTypeMeta == null)
					rawTypeMeta = f.resolveClassMeta(px, p, setter.getGenericParameterTypes()[0], typeVarImpls);
				isUri |= (rawTypeMeta.isUri() || setter.isAnnotationPresent(org.apache.juneau.annotation.URI.class));
				if (px != null) {
					if (swap == null)
						swap = getPropertyPojoSwap(px);
					if (properties != null && ! px.properties().isEmpty())
						properties = split(px.properties());
					bdClasses.addAll(Arrays.asList(px.beanDictionary()));
				}
				if (p != null) {
					if (swap == null)
						swap = getPropertyPojoSwap(p);
					if (properties != null && ! p.bpi().isEmpty())
						properties = split(p.bpi());
					bdClasses.addAll(Arrays.asList(p.dictionary()));
					if (! p.ro().isEmpty())
						readOnly = Boolean.valueOf(p.ro());
					if (! p.wo().isEmpty())
						writeOnly = Boolean.valueOf(p.wo());
				}
				Swap s = setter.getAnnotation(Swap.class);
				if (s != null && swap == null) {
					swap = getPropertyPojoSwap(s);
				}
			}

			if (rawTypeMeta == null)
				return false;

			this.beanRegistry = new BeanRegistry(beanContext, parentBeanRegistry, bdClasses.toArray(new Class<?>[0]));

			isDyna = "*".equals(name);

			// Do some annotation validation.
			ClassInfo ci = rawTypeMeta.getInfo();
			if (getter != null) {
				Class<?>[] pt = getter.getParameterTypes();
				if (isDyna) {
					if (ci.isChildOf(Map.class) && pt.length == 0) {
						isDynaGetterMap = true;
					} else if (pt.length == 1 && pt[0] == String.class) {
						// OK.
					} else {
						return false;
					}
				} else {
					if (! ci.isChildOf(getter.getReturnType()))
						return false;
				}
			}
			if (setter != null) {
				Class<?>[] pt = setter.getParameterTypes();
				if (isDyna) {
					if (pt.length == 2 && pt[0] == String.class) {
						// OK.
					} else {
						return false;
					}
				} else {
					if (pt.length != 1)
						return false;
					if (! ci.isChildOf(pt[0]))
						return false;
				}
			}
			if (field != null) {
				if (isDyna) {
					if (! ClassInfo.of(field.getType()).isChildOf(Map.class))
						return false;
				} else {
					if (! ci.isChildOf(field.getType()))
						return false;
				}
			}

			if (isDyna) {
				rawTypeMeta = rawTypeMeta.getValueType();
				if (rawTypeMeta == null)
					rawTypeMeta = beanContext.object();
			}
			if (rawTypeMeta == null)
				return false;

			if (typeMeta == null)
				typeMeta = (swap != null ? beanContext.getClassMeta(swap.getSwapClass().innerType()) : rawTypeMeta == null ? beanContext.object() : rawTypeMeta);
			if (typeMeta == null)
				typeMeta = rawTypeMeta;

			if (bpro.contains(name) || bpro.contains("*"))
				readOnly = true;
			if (bpwo.contains(name) || bpwo.contains("*"))
				writeOnly = true;

			return true;
		}

		/**
		 * @return A new BeanPropertyMeta object using this builder.
		 */
		public BeanPropertyMeta build() {
			return new BeanPropertyMeta(this);
		}

		@SuppressWarnings("deprecation")
		private PojoSwap getPropertyPojoSwap(BeanProperty p) throws Exception {
			if (! p.format().isEmpty())
				return castOrCreate(PojoSwap.class, StringFormatSwap.class, false, p.format());
			return null;
		}

		private PojoSwap getPropertyPojoSwap(Beanp p) throws Exception {
			if (! p.format().isEmpty())
				return castOrCreate(PojoSwap.class, StringFormatSwap.class, false, p.format());
			return null;
		}

		private PojoSwap getPropertyPojoSwap(Swap s) throws Exception {
			Class<?> c = s.value();
			if (c == Null.class)
				c = s.impl();
			if (c == Null.class)
				return null;
			ClassInfo ci = ClassInfo.of(c);
			if (ci.isChildOf(PojoSwap.class)) {
				PojoSwap ps = castOrCreate(PojoSwap.class, c);
				if (ps.forMediaTypes() != null)
					throw new RuntimeException("TODO - Media types on swaps not yet supported on bean properties.");
				if (ps.withTemplate() != null)
					throw new RuntimeException("TODO - Templates on swaps not yet supported on bean properties.");
				return ps;
			}
			if (ci.isChildOf(Surrogate.class))
				throw new RuntimeException("TODO - Surrogate swaps not yet supported on bean properties.");
			throw new FormattedRuntimeException("Invalid class used in @Swap annotation.  Must be a subclass of PojoSwap or Surrogate.", c);
		}

		BeanPropertyMeta.Builder setGetter(Method getter) {
			setAccessible(getter);
			this.getter = getter;
			return this;
		}

		BeanPropertyMeta.Builder setSetter(Method setter) {
			setAccessible(setter);
			this.setter = setter;
			return this;
		}

		BeanPropertyMeta.Builder setField(Field field) {
			setAccessible(field);
			this.field = field;
			this.innerField = field;
			return this;
		}

		BeanPropertyMeta.Builder setInnerField(Field innerField) {
			this.innerField = innerField;
			return this;
		}

		BeanPropertyMeta.Builder setExtraKeys(Method extraKeys) {
			setAccessible(extraKeys);
			this.extraKeys = extraKeys;
			return this;
		}

		BeanPropertyMeta.Builder setAsConstructorArg() {
			this.isConstructorArg = true;
			return this;
		}

	}

	/**
	 * Creates a new BeanPropertyMeta using the contents of the specified builder.
	 *
	 * @param b The builder to copy fields from.
	 */
	protected BeanPropertyMeta(BeanPropertyMeta.Builder b) {
		this.field = b.field;
		this.innerField = b.innerField;
		this.getter = b.getter;
		this.getterInfo = MethodInfo.of(b.getter);
		this.setter = b.setter;
		this.setterInfo = MethodInfo.of(b.setter);
		this.extraKeys = b.extraKeys;
		this.extraKeysInfo = MethodInfo.of(b.extraKeys);
		this.isUri = b.isUri;
		this.beanMeta = b.beanMeta;
		this.beanContext = b.beanContext;
		this.name = b.name;
		this.rawTypeMeta = b.rawTypeMeta;
		this.typeMeta = b.typeMeta;
		this.properties = b.properties;
		this.swap = b.swap;
		this.beanRegistry = b.beanRegistry;
		this.overrideValue = b.overrideValue;
		this.delegateFor = b.delegateFor;
		this.isDyna = b.isDyna;
		this.isDynaGetterMap = b.isDynaGetterMap;
		this.canRead = b.canRead;
		this.canWrite = b.canWrite;
		this.readOnly = b.readOnly;
		this.writeOnly = b.writeOnly;
		this.hashCode = HashCode.create().add(beanMeta.hashCode()).add(name == null ? 0 : name.hashCode()).get();
	}

	/**
	 * Returns the name of this bean property.
	 *
	 * @return The name of the bean property.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Returns the bean meta that this property belongs to.
	 *
	 * @return The bean meta that this property belongs to.
	 */
	@BeanIgnore
	public BeanMeta<?> getBeanMeta() {
		return beanMeta;
	}

	/**
	 * Returns the getter method for this property.
	 *
	 * @return The getter method for this bean property, or <jk>null</jk> if there is no getter method.
	 */
	public Method getGetter() {
		return getter;
	}

	/**
	 * Returns the setter method for this property.
	 *
	 * @return The setter method for this bean property, or <jk>null</jk> if there is no setter method.
	 */
	public Method getSetter() {
		return setter;
	}

	/**
	 * Returns the field for this property.
	 *
	 * @return The field for this bean property, or <jk>null</jk> if there is no field associated with this bean property.
	 */
	public Field getField() {
		return field;
	}

	/**
	 * Returns the field for this property even if the field is private.
	 *
	 * @return The field for this bean property, or <jk>null</jk> if there is no field associated with this bean property.
	 */
	public Field getInnerField() {
		return innerField;
	}

	/**
	 * Returns the {@link ClassMeta} of the class of this property.
	 *
	 * <p>
	 * If this property or the property type class has a {@link PojoSwap} associated with it, this method returns the
	 * transformed class meta.
	 * This matches the class type that is used by the {@link #get(BeanMap,String)} and
	 * {@link #set(BeanMap,String,Object)} methods.
	 *
	 * @return The {@link ClassMeta} of the class of this property.
	 */
	public ClassMeta<?> getClassMeta() {
		return typeMeta;
	}

	/**
	 * Returns the bean dictionary in use for this bean property.
	 *
	 * <p>
	 * The order of lookup for the dictionary is as follows:
	 * <ol>
	 * 	<li>Dictionary defined via {@link Beanp#dictionary() @Beanp(dictionary)}.
	 * 	<li>Dictionary defined via {@link BeanContext#BEAN_beanDictionary} context property.
	 * </ol>
	 *
	 * @return The bean dictionary in use for this bean property.  Never <jk>null</jk>.
	 */
	public BeanRegistry getBeanRegistry() {
		return beanRegistry;
	}

	/**
	 * Returns <jk>true</jk> if this bean property is a URI.
	 *
	 * <p>
	 * A bean property can be considered a URI if any of the following are true:
	 * <ul>
	 * 	<li>Property class type is {@link URL} or {@link URI}.
	 * 	<li>Property class type is annotated with {@link org.apache.juneau.annotation.URI @URI}.
	 * 	<li>Property getter, setter, or field is annotated with {@link org.apache.juneau.annotation.URI @URI}.
	 * </ul>
	 *
	 * @return <jk>true</jk> if this bean property is a URI.
	 */
	public boolean isUri() {
		return isUri;
	}

	/**
	 * Returns <jk>true</jk> if this bean property is named <js>"*"</js>.
	 *
	 * @return <jk>true</jk> if this bean property is named <js>"*"</js>.
	 */
	public boolean isDyna() {
		return isDyna;
	}

	/**
	 * Returns the override list of properties defined through a {@link Beanp#bpi() @Beanp(bpi)} annotation
	 * on this property.
	 *
	 * @return The list of override properties, or <jk>null</jk> if annotation not specified.
	 */
	public String[] getProperties() {
		return properties;
	}

	/**
	 * Returns the metadata on the property that this metadata is a delegate for.
	 *
	 * @return the metadata on the property that this metadata is a delegate for, or this object if it's not a delegate.
	 */
	public BeanPropertyMeta getDelegateFor() {
		return delegateFor != null ? delegateFor : this;
	}

	/**
	 * Equivalent to calling {@link BeanMap#get(Object)}, but is faster since it avoids looking up the property meta.
	 *
	 * @param m The bean map to get the transformed value from.
	 * @param pName
	 * 	The property name if this is a dyna property (i.e. <js>"*"</js>).
	 * 	<br>Otherwise can be <jk>null</jk>.
	 * @return
	 * 	The property value.
	 * 	<br>Returns <jk>null</jk> if this is a write-only property.
	 */
	public Object get(BeanMap<?> m, String pName) {
		try {

			if (writeOnly)
				return null;

			if (overrideValue != null)
				return overrideValue;

			// Read-only beans have their properties stored in a cache until getBean() is called.
			Object bean = m.bean;
			if (bean == null)
				return m.propertyCache.get(name);

			return toSerializedForm(m.getBeanSession(), getRaw(m, pName));

		} catch (Throwable e) {
			if (beanContext.isIgnoreInvocationExceptionsOnGetters()) {
				if (rawTypeMeta.isPrimitive())
					return rawTypeMeta.getPrimitiveDefault();
				return null;
			}
			throw new BeanRuntimeException(e, beanMeta.c, "Exception occurred while getting property ''{0}''", name);
		}
	}

	/**
	 * Equivalent to calling {@link BeanMap#getRaw(Object)}, but is faster since it avoids looking up the property meta.
	 *
	 * @param m The bean map to get the transformed value from.
	 * @param pName
	 * 	The property name if this is a dyna property (i.e. <js>"*"</js>).
	 * 	<br>Otherwise can be <jk>null</jk>.
	 * @return The raw property value.
	 */
	public Object getRaw(BeanMap<?> m, String pName) {
		try {
			// Read-only beans have their properties stored in a cache until getBean() is called.
			Object bean = m.bean;
			if (bean == null)
				return m.propertyCache.get(name);

			return invokeGetter(bean, pName);

		} catch (Throwable e) {
			if (beanContext.isIgnoreInvocationExceptionsOnGetters()) {
				if (rawTypeMeta.isPrimitive())
					return rawTypeMeta.getPrimitiveDefault();
				return null;
			}
			throw new BeanRuntimeException(e, beanMeta.c, "Exception occurred while getting property ''{0}''", name);
		}
	}

	/**
	 * Converts a raw bean property value to serialized form.
	 * Applies transforms and child property filters.
	 */
	final Object toSerializedForm(BeanSession session, Object o) {
		try {
			o = transform(session, o);
			if (o == null)
				return null;
			if (properties != null) {
				if (rawTypeMeta.isArray()) {
					Object[] a = (Object[])o;
					List l = new DelegateList(rawTypeMeta);
					ClassMeta childType = rawTypeMeta.getElementType();
					for (Object c : a)
						l.add(applyChildPropertiesFilter(session, childType, c));
					return l;
				} else if (rawTypeMeta.isCollection()) {
					Collection c = (Collection)o;
					List l = new ArrayList(c.size());
					ClassMeta childType = rawTypeMeta.getElementType();
					for (Object cc : c)
						l.add(applyChildPropertiesFilter(session, childType, cc));
					return l;
				} else {
					return applyChildPropertiesFilter(session, rawTypeMeta, o);
				}
			}
			return o;
		} catch (SerializeException e) {
			throw new BeanRuntimeException(e);
		}
	}

	/**
	 * Equivalent to calling {@link BeanMap#put(String, Object)}, but is faster since it avoids looking up the property
	 * meta.
	 *
	 * <p>
	 * This is a no-op on a read-only property.
	 *
	 * @param m The bean map to set the property value on.
	 * @param pName
	 * 	The property name if this is a dyna property (i.e. <js>"*"</js>).
	 * 	<br>Otherwise can be <jk>null</jk>.
	 * @param value The value to set.
	 * @return The previous property value.
	 * @throws BeanRuntimeException If property could not be set.
	 */
	public Object set(BeanMap<?> m, String pName, Object value) throws BeanRuntimeException {
		try {

			if (readOnly)
				return null;

			BeanSession session = m.getBeanSession();

			// Convert to raw form.
			value = unswap(session, value);

			if (m.bean == null) {

				// Read-only beans get their properties stored in a cache.
				if (m.propertyCache != null)
					return m.propertyCache.put(name, value);

				throw new BeanRuntimeException("Non-existent bean instance on bean.");
			}

			boolean isMap = rawTypeMeta.isMap();
			boolean isCollection = rawTypeMeta.isCollection();

			if ((! isDyna) && field == null && setter == null && ! (isMap || isCollection)) {
				if ((value == null && beanContext.isIgnoreUnknownNullBeanProperties()) || beanContext.isIgnorePropertiesWithoutSetters())
					return null;
				throw new BeanRuntimeException(beanMeta.c, "Setter or public field not defined on property ''{0}''", name);
			}

			Object bean = m.getBean(true);  // Don't use getBean() because it triggers array creation!

			try {

				Object r = (beanContext.isBeanMapPutReturnsOldValue() || isMap || isCollection) && (getter != null || field != null) ? get(m, pName) : null;
				Class<?> propertyClass = rawTypeMeta.getInnerClass();
				ClassInfo pcInfo = rawTypeMeta.getInfo();

				if (value == null && (isMap || isCollection)) {
					invokeSetter(bean, pName, null);
					return r;
				}

				Class<?> vc = value == null ? null : value.getClass();

				if (isMap && (setter == null || ! pcInfo.isParentOf(vc))) {

					if (! (value instanceof Map)) {
						if (value instanceof CharSequence)
							value = new ObjectMap((CharSequence)value).setBeanSession(session);
						else
							throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}''", name, propertyClass.getName(), findClassName(value));
					}

					Map valueMap = (Map)value;
					Map propMap = (Map)r;
					ClassMeta<?> valueType = rawTypeMeta.getValueType();

					// If the property type is abstract, then we either need to reuse the existing
					// map (if it's not null), or try to assign the value directly.
					if (! rawTypeMeta.canCreateNewInstance()) {
						if (propMap == null) {
							if (setter == null && field == null)
								throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because no setter or public field is defined, and the current value is null", name, propertyClass.getName(), findClassName(value));

							if (propertyClass.isInstance(valueMap)) {
								if (! valueType.isObject()) {
									boolean needsConversion = false;
									for (Map.Entry e : (Set<Map.Entry>)valueMap.entrySet()) {
										Object v = e.getValue();
										if (v != null && ! valueType.getInnerClass().isInstance(v)) {
											needsConversion = true;
											break;
										}
									}
									if (needsConversion)
										valueMap = (Map)session.convertToType(valueMap, rawTypeMeta);
								}
								invokeSetter(bean, pName, valueMap);
								return r;
							}
							throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{2}'' to object of type ''{2}'' because the assigned map cannot be converted to the specified type because the property type is abstract, and the property value is currently null", name, propertyClass.getName(), findClassName(value));
						}
					} else {
						if (propMap == null) {
							propMap = castOrCreate(Map.class, propertyClass);
						} else {
							propMap.clear();
						}
					}

					// Set the values.
					for (Map.Entry e : (Set<Map.Entry>)valueMap.entrySet()) {
						Object k = e.getKey();
						Object v = e.getValue();
						if (! valueType.isObject())
							v = session.convertToType(v, valueType);
						propMap.put(k, v);
					}
					if (setter != null || field != null)
						invokeSetter(bean, pName, propMap);

				} else if (isCollection && (setter == null || ! pcInfo.isParentOf(vc))) {

					if (! (value instanceof Collection)) {
						if (value instanceof CharSequence)
							value = new ObjectList((CharSequence)value).setBeanSession(session);
						else
							throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}''", name, propertyClass.getName(), findClassName(value));
					}

					Collection valueList = (Collection)value;
					Collection propList = (Collection)r;
						ClassMeta elementType = rawTypeMeta.getElementType();

					// If the property type is abstract, then we either need to reuse the existing
					// collection (if it's not null), or try to assign the value directly.
					if (! rawTypeMeta.canCreateNewInstance()) {
						if (propList == null) {
							if (setter == null && field == null)
								throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because no setter or public field is defined, and the current value is null", name, propertyClass.getName(), findClassName(value));

							if (propertyClass.isInstance(valueList)) {
								if (! elementType.isObject()) {
										List l = new ObjectList(valueList);
										for (ListIterator<Object> i = l.listIterator(); i.hasNext(); ) {
											Object v = i.next();
											if (v != null && (! elementType.getInnerClass().isInstance(v))) {
												i.set(session.convertToType(v, elementType));
											}
										}
										valueList = l;
									}
								invokeSetter(bean, pName, valueList);
								return r;
							}
							throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because the assigned map cannot be converted to the specified type because the property type is abstract, and the property value is currently null", name, propertyClass.getName(), findClassName(value));
						}
						propList.clear();
					} else {
						if (propList == null) {
							propList = castOrCreate(Collection.class, propertyClass);
							invokeSetter(bean, pName, propList);
						} else {
							propList.clear();
						}
					}

					// Set the values.
					for (Object v : valueList) {
						if (! elementType.isObject())
							v = session.convertToType(v, elementType);
						propList.add(v);
					}

				} else {
					if (swap != null && value != null && swap.getSwapClass().isParentOf(value.getClass())) {
						value = swap.unswap(session, value, rawTypeMeta);
					} else {
						value = session.convertToType(value, rawTypeMeta);
					}
					invokeSetter(bean, pName, value);
				}

				return r;

			} catch (BeanRuntimeException e) {
				throw e;
			} catch (Exception e) {
				e.printStackTrace();
				if (beanContext.isIgnoreInvocationExceptionsOnSetters()) {
						if (rawTypeMeta.isPrimitive())
							return rawTypeMeta.getPrimitiveDefault();
					return null;
				}
				throw new BeanRuntimeException(e, beanMeta.c, "Error occurred trying to set property ''{0}''", name);
			}
		} catch (ParseException e) {
			throw new BeanRuntimeException(e);
		}
	}

	private Object invokeGetter(Object bean, String pName) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		if (isDyna) {
			Map m = null;
			if (getter != null) {
				if (! isDynaGetterMap)
					return getter.invoke(bean, pName);
				m = (Map)getter.invoke(bean);
			}
			else if (field != null)
				m = (Map)field.get(bean);
			else
				throw new BeanRuntimeException(beanMeta.c, "Getter or public field not defined on property ''{0}''", name);
			return (m == null ? null : m.get(pName));
		}
		if (getter != null)
			return getter.invoke(bean);
		if (field != null)
			return field.get(bean);
		throw new BeanRuntimeException(beanMeta.c, "Getter or public field not defined on property ''{0}''", name);
	}

	private Object invokeSetter(Object bean, String pName, Object val) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		if (isDyna) {
			if (setter != null)
				return setter.invoke(bean, pName, val);
			Map m = null;
			if (field != null)
				m = (Map<String,Object>)field.get(bean);
			else if (getter != null)
				m = (Map<String,Object>)getter.invoke(bean);
			else
				throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because no setter is defined on this property, and the existing property value is null", name, this.getClassMeta().getInnerClass().getName(), findClassName(val));
			return (m == null ? null : m.put(pName, val));
		}
		if (setter != null)
			return setter.invoke(bean, val);
		if (field != null) {
			field.set(bean, val);
			return null;
		}
		throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because no setter is defined on this property, and the existing property value is null", name, this.getClassMeta().getInnerClass().getName(), findClassName(val));
	}

	/**
	 * Returns the {@link Map} object returned by the DynaBean getter.
	 *
	 * <p>
	 * The DynaBean property is the property whose name is <js>"*"</js> and returns a map of "extra" properties on the
	 * bean.
	 *
	 * @param bean The bean.
	 * @return
	 * 	The map returned by the getter, or an empty map if the getter returned <jk>null</jk> or this isn't a DynaBean
	 * 	property.
	 * @throws IllegalArgumentException Thrown by method invocation.
	 * @throws IllegalAccessException Thrown by method invocation.
	 * @throws InvocationTargetException Thrown by method invocation.
	 */
	public Map<String,Object> getDynaMap(Object bean) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		if (isDyna) {
			if (extraKeys != null && getter != null && ! isDynaGetterMap) {
				Map<String,Object> m = new LinkedHashMap<>();
				for (String key : (Collection<String>)extraKeys.invoke(bean))
					m.put(key, getter.invoke(bean, key));
				return m;
			}
			if (getter != null && isDynaGetterMap)
				return (Map)getter.invoke(bean);
			if (field != null)
				return (Map)field.get(bean);
			throw new BeanRuntimeException(beanMeta.c, "Getter or public field not defined on property ''{0}''", name);
		}
		return Collections.EMPTY_MAP;
	}

	/**
	 * Sets an array field on this bean.
	 *
	 * <p>
	 * Works on both <c>Object</c> and primitive arrays.
	 *
	 * @param bean The bean of the field.
	 * @param l The collection to use to set the array field.
	 * @throws IllegalArgumentException Thrown by method invocation.
	 * @throws IllegalAccessException Thrown by method invocation.
	 * @throws InvocationTargetException Thrown by method invocation.
	 */
	protected void setArray(Object bean, List l) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Object array = toArray(l, this.rawTypeMeta.getElementType().getInnerClass());
		invokeSetter(bean, name, array);
	}

	/**
	 * Adds a value to a {@link Collection} or array property.
	 *
	 * <p>
	 * Note that adding values to an array property is inefficient for large arrays since it must copy the array into a
	 * larger array on each operation.
	 *
	 * @param m The bean of the field being set.
	 * @param pName
	 * 	The property name if this is a dyna property (i.e. <js>"*"</js>).
	 * 	<br>Otherwise can be <jk>null</jk>.
	 * @param value The value to add to the field.
	 * @throws BeanRuntimeException If field is not a collection or array.
	 */
	public void add(BeanMap<?> m, String pName, Object value) throws BeanRuntimeException {

		// Read-only beans get their properties stored in a cache.
		if (m.bean == null) {
			if (! m.propertyCache.containsKey(name))
				m.propertyCache.put(name, new ObjectList(m.getBeanSession()));
			((ObjectList)m.propertyCache.get(name)).add(value);
			return;
		}

		BeanSession session = m.getBeanSession();

		boolean isCollection = rawTypeMeta.isCollection();
		boolean isArray = rawTypeMeta.isArray();

		if (! (isCollection || isArray))
			throw new BeanRuntimeException(beanMeta.c, "Attempt to add element to property ''{0}'' which is not a collection or array", name);

		Object bean = m.getBean(true);

		ClassMeta<?> elementType = rawTypeMeta.getElementType();

		try {
			Object v = session.convertToType(value, elementType);

			if (isCollection) {
				Collection c = (Collection)invokeGetter(bean, pName);

				if (c != null) {
					c.add(v);
					return;
				}

				if (rawTypeMeta.canCreateNewInstance())
					c = (Collection)rawTypeMeta.newInstance();
				else
					c = new ObjectList(session);

				c.add(v);

				invokeSetter(bean, pName, c);

			} else /* isArray() */ {

				if (m.arrayPropertyCache == null)
					m.arrayPropertyCache = new TreeMap<>();

				List l = m.arrayPropertyCache.get(name);
				if (l == null) {
					l = new LinkedList();  // ArrayLists and LinkLists appear to perform equally.
					m.arrayPropertyCache.put(name, l);

					// Copy any existing array values into the temporary list.
					Object oldArray = invokeGetter(bean, pName);
					copyToList(oldArray, l);
				}

				// Add new entry to our array.
				l.add(v);
			}

		} catch (BeanRuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new BeanRuntimeException(e);
		}
	}

	/**
	 * Adds a value to a {@link Map} or bean property.
	 *
	 * @param m The bean of the field being set.
	 * @param pName
	 * 	The property name if this is a dyna property (i.e. <js>"*"</js>).
	 * 	<br>Otherwise can be <jk>null</jk>.
	 * @param key The key to add to the field.
	 * @param value The value to add to the field.
	 * @throws BeanRuntimeException If field is not a map or array.
	 */
	public void add(BeanMap<?> m, String pName, String key, Object value) throws BeanRuntimeException {

 		// Read-only beans get their properties stored in a cache.
		if (m.bean == null) {
			if (! m.propertyCache.containsKey(name))
				m.propertyCache.put(name, new ObjectMap(m.getBeanSession()));
			((ObjectMap)m.propertyCache.get(name)).append(key.toString(), value);
			return;
		}

		BeanSession session = m.getBeanSession();

		boolean isMap = rawTypeMeta.isMap();
		boolean isBean = rawTypeMeta.isBean();

		if (! (isBean || isMap))
			throw new BeanRuntimeException(beanMeta.c, "Attempt to add key/value to property ''{0}'' which is not a map or bean", name);

		Object bean = m.getBean(true);

		ClassMeta<?> elementType = rawTypeMeta.getElementType();

		try {
			Object v = session.convertToType(value, elementType);

			if (isMap) {
				Map map = (Map)invokeGetter(bean, pName);

				if (map != null) {
					map.put(key, v);
					return;
				}

				if (rawTypeMeta.canCreateNewInstance())
					map = (Map)rawTypeMeta.newInstance();
				else
					map = new ObjectMap(session);

				map.put(key, v);

				invokeSetter(bean, pName, map);

			} else /* isBean() */ {

				Object b = invokeGetter(bean, pName);

				if (b != null) {
					BeanMap bm = session.toBeanMap(b);
					bm.put(key, v);
					return;
				}

				if (rawTypeMeta.canCreateNewInstance(m.getBean(false))) {
					b = rawTypeMeta.newInstance();
					BeanMap bm = session.toBeanMap(b);
					bm.put(key, v);
				}

				invokeSetter(bean, pName, b);
			}

		} catch (BeanRuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new BeanRuntimeException(e);
		}
	}

	/**
	 * Returns all instances of the specified annotation in the hierarchy of this bean property.
	 *
	 * <p>
	 * Searches through the class hierarchy (e.g. superclasses, interfaces, packages) for all instances of the
	 * specified annotation.
	 *
	 * @param a The class to find annotations for.
	 * @return A list of annotations ordered in child-to-parent order.  Never <jk>null</jk>.
	 */
	public <A extends Annotation> List<A> findAnnotations(Class<A> a) {
		List<A> l = new LinkedList<>();
		if (field != null) {
			addIfNotNull(l, field.getAnnotation(a));
			ClassInfo.of(field.getType()).appendAnnotations(l, a);
		}
		if (getter != null) {
			addIfNotNull(l, MethodInfo.of(getter).getAnnotation(a));
			ClassInfo.of(getter.getReturnType()).appendAnnotations(l, a);
		}
		if (setter != null) {
			addIfNotNull(l, MethodInfo.of(setter).getAnnotation(a));
			ClassInfo.of(setter.getReturnType()).appendAnnotations(l, a);
		}
		if (extraKeys != null) {
			addIfNotNull(l, MethodInfo.of(extraKeys).getAnnotation(a));
			ClassInfo.of(extraKeys.getReturnType()).appendAnnotations(l, a);
		}

		getBeanMeta().getClassMeta().getInfo().appendAnnotations(l, a);
		return l;
	}

	/**
	 * Returns the specified annotation on the field or methods that define this property.
	 *
	 * <p>
	 * This method will search up the parent class/interface hierarchy chain to search for the annotation on
	 * overridden getters and setters.
	 *
	 * @param a The annotation to search for.
	 * @return The annotation, or <jk>null</jk> if it wasn't found.
	 */
	public <A extends Annotation> A findAnnotation(Class<A> a) {
		A t = null;
		if (field != null)
			t = field.getAnnotation(a);
		if (t == null && getter != null)
			t = getterInfo.getAnnotation(a);
		if (t == null && setter != null)
			t = setterInfo.getAnnotation(a);
		if (t == null && extraKeys != null)
			t = extraKeysInfo.getAnnotation(a);
		if (t == null)
			t = typeMeta.getInfo().getAnnotation(a);
		return t;
	}

	private Object transform(BeanSession session, Object o) throws SerializeException {
		try {
			// First use swap defined via @Beanp.
			if (swap != null)
				return swap.swap(session, o);
			if (o == null)
				return null;
			// Otherwise, look it up via bean context.
			if (rawTypeMeta.hasChildPojoSwaps()) {
				PojoSwap f = rawTypeMeta.getChildPojoSwapForSwap(o.getClass());
				if (f != null)
					return f.swap(session, o);
			}
			return o;
		} catch (SerializeException e) {
			throw e;
		} catch (Exception e) {
			throw new SerializeException(e);
		}
	}

	private Object unswap(BeanSession session, Object o) throws ParseException {
		try {
			if (swap != null)
				return swap.unswap(session, o, rawTypeMeta);
			if (o == null)
				return null;
			if (rawTypeMeta.hasChildPojoSwaps()) {
				PojoSwap f = rawTypeMeta.getChildPojoSwapForUnswap(o.getClass());
				if (f != null)
					return f.unswap(session, o, rawTypeMeta);
			}
			return o;
		} catch (ParseException e) {
			throw e;
		} catch (Exception e) {
			throw new ParseException(e);
		}
	}

	private Object applyChildPropertiesFilter(BeanSession session, ClassMeta cm, Object o) {
		if (o == null)
			return null;
		if (cm.isBean())
			return new BeanMap(session, o, new BeanMetaFiltered(cm.getBeanMeta(), properties));
		if (cm.isMap())
			return new FilteredMap(cm, (Map)o, properties);
		if (cm.isObject()) {
			if (o instanceof Map)
				return new FilteredMap(cm, (Map)o, properties);
			BeanMeta bm = beanContext.getBeanMeta(o.getClass());
			if (bm != null)
				return new BeanMap(session, o, new BeanMetaFiltered(cm.getBeanMeta(), properties));
		}
		return o;
	}

	private static String findClassName(Object o) {
		if (o == null)
			return null;
		if (o instanceof Class)
			return ((Class<?>)o).getName();
		return o.getClass().getName();
	}

	@Override /* Object */
	public String toString() {
		return name + ": " + this.rawTypeMeta.getInnerClass().getName() + ", field=["+field+"], getter=["+getter+"], setter=["+setter+"]";
	}

	/**
	 * Returns <jk>true</jk> if this property can be read.
	 *
	 * @return <jk>true</jk> if this property can be read.
	 */
	public boolean canRead() {
		return canRead;
	}

	/**
	 * Returns <jk>true</jk> if this property can be written.
	 *
	 * @return <jk>true</jk> if this property can be written.
	 */
	public boolean canWrite() {
		return canWrite;
	}

	/**
	 * Returns <jk>true</jk> if this property is read-only.
	 *
	 * <p>
	 * This implies the property MIGHT be writable, but that parsers should not set a value for it.
	 *
	 * @return <jk>true</jk> if this property is read-only.
	 */
	public boolean isReadOnly() {
		return readOnly;
	}

	/**
	 * Returns <jk>true</jk> if this property is write-only.
	 *
	 * <p>
	 * This implies the property MIGHT be readable, but that serializers should not serialize it.
	 *
	 * @return <jk>true</jk> if this property is write-only.
	 */
	protected boolean isWriteOnly() {
		return writeOnly;
	}

	@Override /* Object */
	public int hashCode() {
		return hashCode;
	}

	@Override /* Object */
	public boolean equals(Object o) {
		if (o == null || ! (o instanceof BeanPropertyMeta))
			return false;
		BeanPropertyMeta o2 = (BeanPropertyMeta)o;
		return o2.beanMeta.equals(this.beanMeta) && isEquals(o2.name, this.name);
	}
}