// ***************************************************************************************************************************
// * 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.transform;

import static org.apache.juneau.internal.StringUtils.*;
import static java.util.Arrays.*;

import java.beans.*;
import java.util.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.reflect.*;

/**
 * Builder class for {@link BeanFilter} objects.
 *
 * <p>
 * This class is the programmatic equivalent to the {@link Bean @Bean} annotation.
 *
 * <p>
 * The general approach to defining bean filters is to create subclasses from this class and call methods to
 * set various attributes
 * <p class='bcode w800'>
 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
 *
 * 		<jc>// Must provide a no-arg constructor!</jc>
 * 		<jk>public</jk> MyFilter() {
 *
 * 			<jc>// Call one or more configuration methods.</jc>
 * 			bpi(<js>"foo,bar,baz"</js>);
 * 			sortProperties();
 * 			propertyNamer(PropertyNamerULC.<jk>class</jk>);
 * 		}
 * 	}
 *
 * 	<jc>// Register it with a serializer or parser.</jc>
 * 	WriterSerializer s = JsonSerializer
 * 		.<jsm>create</jsm>()
 * 		.beanFilters(MyFilter.<jk>class</jk>)
 * 		.build();
 * </p>
 *
 * <ul class='seealso'>
 * 	<li class='link'>{@doc juneau-marshall.Transforms.BeanFilters}
 * </ul>
 *
 * @param <T> The bean type that this filter applies to.
 */
public class BeanFilterBuilder<T> {

	Class<?> beanClass;
	String typeName;
	Set<String>
		bpi = new LinkedHashSet<>(),
		bpx = new LinkedHashSet<>(),
		bpro = new LinkedHashSet<>(),
		bpwo = new LinkedHashSet<>();
	Class<?> interfaceClass, stopClass;
	boolean sortProperties, fluentSetters;
	Object propertyNamer;
	List<Class<?>> dictionary;
	Object propertyFilter;

	/**
	 * Constructor.
	 *
	 * <p>
	 * Bean class is determined through reflection of the parameter type.
	 */
	protected BeanFilterBuilder() {
		beanClass = ClassInfo.of(this.getClass()).getParameterType(0, BeanFilterBuilder.class);
	}

	/**
	 * Constructor.
	 *
	 * @param beanClass The bean class that this filter applies to.
	 */
	protected BeanFilterBuilder(Class<?> beanClass) {
		this.beanClass = beanClass;
	}

	/**
	 * Configuration property:  Bean dictionary type name.
	 *
	 * <p>
	 * Specifies the dictionary type name for this bean.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			typeName(<js>"mybean"</js>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer or parser.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Produces:  "{_type:'mybean', ...}"</jc>
	 * 	String json = s.serialize(<jk>new</jk> MyBean());
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#typeName()}
	 * </ul>
	 *
	 * @param value The new value for this setting.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> typeName(String value) {
		this.typeName = value;
		return this;
	}

	/**
	 * Configuration property:  Bean property includes.
	 *
	 * @deprecated Use {@link #bpi(String...)}
	 */
	@SuppressWarnings("javadoc")
	@Deprecated public BeanFilterBuilder<T> properties(String...value) {
		this.bpi = new LinkedHashSet<>();
		for (String v : value)
			bpi.addAll(asList(split(v)));
		return this;
	}

	/**
	 * Configuration property:  Bean property excludes.
	 *
	 * @deprecated Use {@link #bpx(String...)}
	 */
	@SuppressWarnings("javadoc")
	@Deprecated public BeanFilterBuilder<T> excludeProperties(String...value) {
		this.bpx = new LinkedHashSet<>();
		for (String v : value)
			bpx.addAll(asList(split(v)));
		return this;
	}

	/**
	 * Configuration property:  Bean interface class.
	 *
	 * Identifies a class to be used as the interface class for this and all subclasses.
	 *
	 * <p>
	 * When specified, only the list of properties defined on the interface class will be used during serialization.
	 * <br>Additional properties on subclasses will be ignored.
	 *
	 * <p class='bcode w800'>
	 * 	<jc>// Parent class</jc>
	 * 	<jk>public abstract class</jk> A {
	 * 		<jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
	 * 	}
	 *
	 * 	<jc>// Sub class</jc>
	 * 	<jk>public class</jk> A1 <jk>extends</jk> A {
	 * 		<jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>;
	 * 	}
	 *
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> AFilter <jk>extends</jk> BeanFilterBuilder&lt;A&gt; {
	 * 		<jk>public</jk> AFilter() {
	 * 			interfaceClass(A.<jk>class</jk>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(AFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Use it.</jc>
	 * 	A1 a1 = <jk>new</jk> A1();
	 * 	String r = s.serialize(a1);
	 * 	<jsm>assertEquals</jsm>(<js>"{f0:'f0'}"</js>, r);  <jc>// Note f1 is not serialized</jc>
	 * </p>
	 *
	 * <p>
	 * Note that this filter can be used on the parent class so that it filters to all child classes, or can be set
	 * individually on the child classes.
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#interfaceClass()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_beanFilters}
	 * </ul>
	 *
	 * @param value The new value for this setting.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> interfaceClass(Class<?> value) {
		this.interfaceClass = value;
		return this;
	}

	/**
	 * Configuration property:  Bean stop class.
	 *
	 * <p>
	 * Identifies a stop class for this class and all subclasses.
	 *
	 * <p>
	 * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}.
	 * <br>Any properties in the stop class or in its base classes will be ignored during analysis.
	 *
	 * <p>
	 * For example, in the following class hierarchy, instances of <c>C3</c> will include property <c>p3</c>,
	 * but not <c>p1</c> or <c>p2</c>.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jk>public class</jk> C1 {
	 * 		<jk>public int</jk> getP1();
	 * 	}
	 *
	 * 	<jk>public class</jk> C2 <jk>extends</jk> C1 {
	 * 		<jk>public int</jk> getP2();
	 * 	}
	 *
	 * 	<jk>public class</jk> C3 <jk>extends</jk> C2 {
	 * 		<jk>public int</jk> getP3();
	 * 	}
	 *
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> C3Filter <jk>extends</jk> BeanFilterBuilder&lt;C3&gt; {
	 * 		<jk>public</jk> C3Filter() {
	 * 			stopClass(C2.<jk>class</jk>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(C3Filter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Serializes property 'p3', but NOT 'p1' or 'p2'.</jc>
	 * 	String json = s.serialize(<jk>new</jk> C3());
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#stopClass()}
	 * </ul>
	 *
	 * @param value The new value for this setting.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> stopClass(Class<?> value) {
		this.stopClass = value;
		return this;
	}

	/**
	 * Configuration property:  Sort bean properties.
	 *
	 * <p>
	 * When <jk>true</jk>, all bean properties will be serialized and access in alphabetical order.
	 * <br>Otherwise, the natural order of the bean properties is used which is dependent on the JVM vendor.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			sortProperties();
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Properties will be sorted alphabetically.</jc>
	 * 	String json = s.serialize(<jk>new</jk> MyBean());
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#sort()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_sortProperties}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this property.
	 * 	<br>The default is <jk>false</jk>.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> sortProperties(boolean value) {
		this.sortProperties = value;
		return this;
	}

	/**
	 * Configuration property:  Sort bean properties.
	 *
	 * <p>
	 * Shortcut for calling <code>sortProperties(<jk>true</jk>)</code>.
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#sort()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_sortProperties}
	 * </ul>
	 *
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> sortProperties() {
		this.sortProperties = true;
		return this;
	}

	/**
	 * Configuration property:  Find fluent setters.
	 *
	 * <p>
	 * When enabled, fluent setters are detected on beans.
	 *
	 * <p>
	 * Fluent setters must have the following attributes:
	 * <ul>
	 * 	<li>Public.
	 * 	<li>Not static.
	 * 	<li>Take in one parameter.
	 * 	<li>Return the bean itself.
	 * </ul>
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			fluentSetters();
	 * 		}
	 * 	}
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#fluentSetters()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_fluentSetters}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this property.
	 * 	<br>The default is <jk>false</jk>.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> fluentSetters(boolean value) {
		this.fluentSetters = value;
		return this;
	}

	/**
	 * Configuration property:  Find fluent setters.
	 *
	 * <p>
	 * Shortcut for calling <code>fluentSetters(<jk>true</jk>)</code>.
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#fluentSetters()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_fluentSetters}
	 * </ul>
	 *
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> fluentSetters() {
		this.fluentSetters = true;
		return this;
	}

	/**
	 * Configuration property:  Bean property namer
	 *
	 * <p>
	 * The class to use for calculating bean property names.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			<jc>// Use Dashed-Lower-Case property names.</jc>
	 * 			<jc>// (e.g. "foo-bar-url" instead of "fooBarURL")</jc>
	 * 			propertyNamer(PropertyNamerDLC.<jk>class</jk>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer or parser.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Properties names will be Dashed-Lower-Case.</jc>
	 * 	String json = s.serialize(<jk>new</jk> MyBean());
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#propertyNamer()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_propertyNamer}
	 * 	<li class='jc'>{@link PropertyNamer}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this setting.
	 * 	<br>The default is {@link PropertyNamerDefault}.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> propertyNamer(Class<? extends PropertyNamer> value) {
		this.propertyNamer = value;
		return this;
	}

	/**
	 * Configuration property:  Bean dictionary.
	 *
	 * <p>
	 * Adds to the list of classes that make up the bean dictionary for this bean.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			<jc>// Our bean contains generic collections of Foo and Bar objects.</jc>
	 * 			beanDictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a parser.</jc>
	 * 	ReaderParser p = JsonParser
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Instantiate our bean.</jc>
	 * 	MyBean myBean = p.parse(json);
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#dictionary()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_beanDictionary}
	 * </ul>
	 *
	 * @param values
	 * 	The values to add to this property.
	 * @return This object (for method chaining).
	 * @deprecated Use {@link #dictionary(Class...)}.
	 */
	@Deprecated
	public BeanFilterBuilder<T> beanDictionary(Class<?>...values) {
		if (dictionary == null)
			dictionary = new ArrayList<>(Arrays.asList(values));
		else for (Class<?> cc : values)
			dictionary.add(cc);
		return this;
	}

	/**
	 * Configuration property:  Bean property includes.
	 *
	 * <p>
	 * Specifies the set and order of names of properties associated with the bean class.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			bpi(<js>"foo,bar,baz"</js>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Only serializes the properties 'foo', 'bar', and 'baz'.</jc>
	 * 	String json = s.serialize(<jk>new</jk> MyBean());
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#bpi()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_bpi}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this setting.
	 * 	<br>Values can contain comma-delimited list of property names.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> bpi(String...value) {
		this.bpi = new LinkedHashSet<>();
		for (String v : value)
			bpi.addAll(asList(split(v)));
		return this;
	}

	/**
	 * Configuration property:  Bean property excludes.
	 *
	 * <p>
	 * Specifies properties to exclude from the bean class.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			bpx(<js>"foo,bar"</js>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Serializes all properties except for 'foo' and 'bar'.</jc>
	 * 	String json = s.serialize(<jk>new</jk> MyBean());
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#bpx()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_bpx}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this setting.
	 * 	<br>Values can contain comma-delimited list of property names.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> bpx(String...value) {
		this.bpx = new LinkedHashSet<>();
		for (String v : value)
			bpx.addAll(asList(split(v)));
		return this;
	}

	/**
	 * Configuration property:  Read-only bean properties.
	 *
	 * <p>
	 * Specifies one or more properties on a bean that are read-only despite having valid getters.
	 * Serializers will serialize such properties as usual, but parsers will silently ignore them.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			bpro(<js>"foo,bar"</js>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a parser.</jc>
	 *  ReaderParser p = JsonParser
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Parsers all properties except for 'foo' and 'bar'.</jc>
	 * 	MyBean b = p.parse(<js>"..."</js>, MyBean.<jk>class</jk>);
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#bpro()}
	 * 	<li class='ja'>{@link Beanp#ro()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_bpro}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this setting.
	 * 	<br>Values can contain comma-delimited list of property names.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> bpro(String...value) {
		this.bpro = new LinkedHashSet<>();
		for (String v : value)
			bpro.addAll(asList(split(v)));
		return this;
	}

	/**
	 * Configuration property:  Write-only bean properties.
	 *
	 * <p>
	 * Specifies one or more properties on a bean that are write-only despite having valid setters.
	 * Parsers will parse such properties as usual, but serializers will silently ignore them.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			bpwo(<js>"foo,bar"</js>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer.</jc>
	 *  WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Serializes all properties except for 'foo' and 'bar'.</jc>
	 * 	String json = s.serialize(<jk>new</jk> MyBean());
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#bpwo()}
	 * 	<li class='ja'>{@link Beanp#wo()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_bpwo}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this setting.
	 * 	<br>Values can contain comma-delimited list of property names.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> bpwo(String...value) {
		this.bpwo = new LinkedHashSet<>();
		for (String v : value)
			bpwo.addAll(asList(split(v)));
		return this;
	}

	/**
	 * Configuration property:  Bean dictionary.
	 *
	 * <p>
	 * Adds to the list of classes that make up the bean dictionary for this bean.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			<jc>// Our bean contains generic collections of Foo and Bar objects.</jc>
	 * 			beanDictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a parser.</jc>
	 * 	ReaderParser p = JsonParser
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 *
	 * 	<jc>// Instantiate our bean.</jc>
	 * 	MyBean myBean = p.parse(json);
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#dictionary()}
	 * 	<li class='jf'>{@link BeanContext#BEAN_beanDictionary}
	 * </ul>
	 *
	 * @param values
	 * 	The values to add to this property.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> dictionary(Class<?>...values) {
		if (dictionary == null)
			dictionary = new ArrayList<>(Arrays.asList(values));
		else for (Class<?> cc : values)
			dictionary.add(cc);
		return this;
	}

	/**
	 * Configuration property:  Property filter.
	 *
	 * <p>
	 * The property filter to use for intercepting and altering getter and setter calls.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <p class='bcode w800'>
	 * 	<jc>// Define our filter.</jc>
	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
	 * 		<jk>public</jk> MyFilter() {
	 * 			<jc>// Our bean contains generic collections of Foo and Bar objects.</jc>
	 * 			propertyFilter(AddressPropertyFilter.<jk>class</jk>);
	 * 		}
	 * 	}
	 *
	 * 	<jc>// Register it with a serializer or parser.</jc>
	 * 	WriterSerializer s = JsonSerializer
	 * 		.<jsm>create</jsm>()
	 * 		.beanFilters(MyFilter.<jk>class</jk>)
	 * 		.build();
	 * </p>
	 *
	 * <ul class='seealso'>
	 * 	<li class='ja'>{@link Bean#propertyFilter()}
	 * 	<li class='jc'>{@link PropertyFilter}
	 * </ul>
	 *
	 * @param value
	 * 	The new value for this setting.
	 * 	<br>The default value is {@link PropertyFilter}.
	 * @return This object (for method chaining).
	 */
	public BeanFilterBuilder<T> propertyFilter(Class<? extends PropertyFilter> value) {
		this.propertyFilter = value;
		return this;
	}

	/**
	 * Creates a {@link BeanFilter} with settings in this builder class.
	 *
	 * @return A new {@link BeanFilter} instance.
	 */
	public BeanFilter build() {
		return new BeanFilter(this);
	}
}
