// ***************************************************************************************************************************
// * 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.*;
import org.apache.juneau.utils.*;

/**
 * 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 MetadataMap extMeta;                        // Extended metadata
	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;

	/**
	 * 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;
		MetadataMap extMeta = new MetadataMap();
		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.extMeta = b.extMeta;
		this.isDyna = b.isDyna;
		this.isDynaGetterMap = b.isDynaGetterMap;
		this.canRead = b.canRead;
		this.canWrite = b.canWrite;
		this.readOnly = b.readOnly;
		this.writeOnly = b.writeOnly;
	}

	/**
	 * 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 language-specified extended metadata on this bean property.
	 *
	 * @param c The name of the metadata class to create.
	 * @return Extended metadata on this bean property.  Never <jk>null</jk>.
	 */
	public <M extends BeanPropertyMetaExtended> M getExtendedMeta(Class<M> c) {
		if (delegateFor != null)
			return delegateFor.getExtendedMeta(c);
		return extMeta.get(c, 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.
	 * @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.
	 * @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.
	 * @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.
	 * @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.
	 * @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;
	}
}