/*
 *  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
 *
 *      https://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.tools.ant;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.tools.ant.taskdefs.PreSetDef;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.util.StringUtils;

/**
 * Helper class that collects the methods a task or nested element
 * holds to set attributes, create nested elements or hold PCDATA
 * elements.
 *
 * It contains hashtables containing classes that use introspection
 * to handle all the invocation of the project-component specific methods.
 *
 * This class is somewhat complex, as it implements the O/X mapping between
 * Ant XML and Java class instances. This is not the best place for someone new
 * to Ant to start contributing to the codebase, as a change here can break the
 * entire system in interesting ways. Always run a full test of Ant before checking
 * in/submitting changes to this file.
 *
 * The class is final and has a private constructor.
 * To get an instance for a specific (class,project) combination,
 * use {@link #getHelper(Project,Class)}.
 * This may return an existing version, or a new one
 * ...do not make any assumptions about its uniqueness, or its validity after the Project
 * instance has finished its build.
 *
 */
public final class IntrospectionHelper {

    /**
     * Helper instances we've already created (Class.getName() to IntrospectionHelper).
     */
    private static final Map<String, IntrospectionHelper> HELPERS = new Hashtable<>();

    /**
     * Map from primitive types to wrapper classes for use in
     * createAttributeSetter (Class to Class). Note that char
     * and boolean are in here even though they get special treatment
     * - this way we only need to test for the wrapper class.
     */
    private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_MAP = new HashMap<>(8);

    // Set up PRIMITIVE_TYPE_MAP
    static {
        final Class<?>[] primitives = {Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE,
                              Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE};
        final Class<?>[] wrappers = {Boolean.class, Byte.class, Character.class, Short.class,
                            Integer.class, Long.class, Float.class, Double.class};
        for (int i = 0; i < primitives.length; i++) {
            PRIMITIVE_TYPE_MAP.put(primitives[i], wrappers[i]);
        }
    }

    private static final int MAX_REPORT_NESTED_TEXT = 20;
    private static final String ELLIPSIS = "...";

    /**
     * Map from attribute names to attribute types
     * (String to Class).
     */
    private final Map<String, Class<?>> attributeTypes = new Hashtable<>();

    /**
     * Map from attribute names to attribute setter methods
     * (String to AttributeSetter).
     */
    private final Map<String, AttributeSetter> attributeSetters = new Hashtable<>();

    /**
     * Map from attribute names to nested types
     * (String to Class).
     */
    private final Map<String, Class<?>> nestedTypes = new Hashtable<>();

    /**
     * Map from attribute names to methods to create nested types
     * (String to NestedCreator).
     */
    private final Map<String, NestedCreator> nestedCreators = new Hashtable<>();

    /**
     * Vector of methods matching add[Configured](Class) pattern.
     */
    private final List<Method> addTypeMethods = new ArrayList<>();

    /**
     * The method to invoke to add PCDATA.
     */
    private final Method addText;

    /**
     * The class introspected by this instance.
     */
    private final Class<?> bean;

    /**
     * Sole constructor, which is private to ensure that all
     * IntrospectionHelpers are created via {@link #getHelper(Class) getHelper}.
     * Introspects the given class for bean-like methods.
     * Each method is examined in turn, and the following rules are applied:
     * <p>
     * <ul>
     * <li>If the method is <code>Task.setLocation(Location)</code>,
     * <code>Task.setTaskType(String)</code>
     * or <code>TaskContainer.addTask(Task)</code>, it is ignored. These
     * methods are handled differently elsewhere.
     * <li><code>void addText(String)</code> is recognised as the method for
     * adding PCDATA to a bean.
     * <li><code>void setFoo(Bar)</code> is recognised as a method for
     * setting the value of attribute <code>foo</code>, so long as
     * <code>Bar</code> is non-void and is not an array type.
     * As of Ant 1.8, a Resource or FileProvider parameter overrides a java.io.File parameter;
     * in practice the only effect of this is to allow objects rendered from
     * the 1.8 PropertyHelper implementation to be used as Resource parameters,
     * since Resources set from Strings are resolved as project-relative files
     * to preserve backward compatibility.  Beyond this, non-String
     * parameter types always overload String parameter types; these are
     * the only guarantees made in terms of priority.
     * <li><code>Foo createBar()</code> is recognised as a method for
     * creating a nested element called <code>bar</code> of type
     * <code>Foo</code>, so long as <code>Foo</code> is not a primitive or
     * array type.
     * <li><code>void addConfiguredFoo(Bar)</code> is recognised as a
     * method for storing a pre-configured element called
     * <code>foo</code> and of type <code>Bar</code>, so long as
     * <code>Bar</code> is not an array, primitive or String type.
     * <code>Bar</code> must have an accessible constructor taking no
     * arguments.
     * <li><code>void addFoo(Bar)</code> is recognised as a method for storing
     * an element called <code>foo</code> and of type <code>Bar</code>, so
     * long as <code>Bar</code> is not an array, primitive or String type.
     * <code>Bar</code> must have an accessible constructor taking no
     * arguments. This is distinct from the 'addConfigured' idiom in that
     * the nested element is added to the parent immediately after it is
     * constructed; in practice this means that <code>addFoo(Bar)</code> should
     * do little or nothing with its argument besides storing it for later use.
     * </ul>
     * Note that only one method is retained to create/set/addConfigured/add
     * any element or attribute.
     *
     * @param bean The bean type to introspect.
     *             Must not be <code>null</code>.
     *
     * @see #getHelper(Class)
     */
    private IntrospectionHelper(final Class<?> bean) {
        this.bean = bean;
        Method addTextMethod = null;
        for (final Method m : bean.getMethods()) {
            final String name = m.getName();
            final Class<?> returnType = m.getReturnType();
            final Class<?>[] args = m.getParameterTypes();

            // check of add[Configured](Class) pattern
            if (args.length == 1 && Void.TYPE.equals(returnType)
                    && ("add".equals(name) || "addConfigured".equals(name))) {
                insertAddTypeMethod(m);
                continue;
            }
            // not really user settable properties on tasks/project components
            if (ProjectComponent.class.isAssignableFrom(bean)
                    && args.length == 1 && isHiddenSetMethod(name, args[0])) {
                continue;
            }
            // hide addTask for TaskContainers
            if (isContainer() && args.length == 1 && "addTask".equals(name)
                    && Task.class.equals(args[0])) {
                continue;
            }
            if ("addText".equals(name) && Void.TYPE.equals(returnType)
                    && args.length == 1 && String.class.equals(args[0])) {
                addTextMethod = m;
            } else if (name.startsWith("set") && Void.TYPE.equals(returnType)
                    && args.length == 1 && !args[0].isArray()) {
                final String propName = getPropertyName(name, "set");
                AttributeSetter as = attributeSetters.get(propName);
                if (as != null) {
                    if (String.class.equals(args[0])) {
                        /*
                            Ignore method m, as there is an overloaded
                            form of this method that takes in a
                            non-string argument, which gains higher
                            priority.
                        */
                        continue;
                    }
                    if (File.class.equals(args[0])) {
                        // Ant Resources/FileProviders override java.io.File
                        if (Resource.class.equals(as.type) || FileProvider.class.equals(as.type)) {
                            continue;
                        }
                    }
                    /*
                        In cases other than those just explicitly covered,
                        we just override that with the new one.
                        This mechanism does not guarantee any specific order
                        in which the methods will be selected: so any code
                        that depends on the order in which "set" methods have
                        been defined, is not guaranteed to be selected in any
                        particular order.
                    */
                }
                as = createAttributeSetter(m, args[0], propName);
                if (as != null) {
                    attributeTypes.put(propName, args[0]);
                    attributeSetters.put(propName, as);
                }
            } else if (name.startsWith("create") && !returnType.isArray()
                    && !returnType.isPrimitive() && args.length == 0) {

                final String propName = getPropertyName(name, "create");
                // Check if a create of this property is already present
                // add takes preference over create for CB purposes
                if (nestedCreators.get(propName) == null) {
                    nestedTypes.put(propName, returnType);
                    nestedCreators.put(propName, new CreateNestedCreator(m));
                }
            } else if (name.startsWith("addConfigured")
                    && Void.TYPE.equals(returnType) && args.length == 1
                    && !String.class.equals(args[0])
                    && !args[0].isArray() && !args[0].isPrimitive()) {
                try {
                    Constructor<?> constructor = null;
                    try {
                        constructor = args[0].getConstructor();
                    } catch (final NoSuchMethodException ex) {
                        constructor = args[0].getConstructor(Project.class);
                    }
                    final String propName = getPropertyName(name, "addConfigured");
                    nestedTypes.put(propName, args[0]);
                    nestedCreators.put(propName, new AddNestedCreator(m,
                        constructor, AddNestedCreator.ADD_CONFIGURED));
                } catch (final NoSuchMethodException nse) {
                    // ignore
                }
            } else if (name.startsWith("add")
                    && Void.TYPE.equals(returnType) && args.length == 1
                    && !String.class.equals(args[0])
                    && !args[0].isArray() && !args[0].isPrimitive()) {
                try {
                    Constructor<?> constructor = null;
                    try {
                        constructor = args[0].getConstructor();
                    } catch (final NoSuchMethodException ex) {
                        constructor = args[0].getConstructor(Project.class);
                    }
                    final String propName = getPropertyName(name, "add");
                    if (nestedTypes.get(propName) != null) {
                        /*
                         *  Ignore this method as there is an addConfigured
                         *  form of this method that has a higher
                         *  priority
                         */
                        continue;
                    }
                    nestedTypes.put(propName, args[0]);
                    nestedCreators.put(propName, new AddNestedCreator(m,
                            constructor, AddNestedCreator.ADD));
                } catch (final NoSuchMethodException nse) {
                    // ignore
                }
            }
        }
        addText = addTextMethod;
    }

    /**
     * Certain set methods are part of the Ant core interface to tasks and
     * therefore not to be considered for introspection
     *
     * @param name the name of the set method
     * @param type the type of the set method's parameter
     * @return true if the given set method is to be hidden.
     */
    private boolean isHiddenSetMethod(final String name, final Class<?> type) {
        return "setLocation".equals(name) && Location.class.equals(type)
                || "setTaskType".equals(name) && String.class.equals(type);
    }

    /**
     * Returns a helper for the given class, either from the cache
     * or by creating a new instance.
     *
     * @param c The class for which a helper is required.
     *          Must not be <code>null</code>.
     *
     * @return a helper for the specified class
     */
    public static synchronized IntrospectionHelper getHelper(final Class<?> c) {
        return getHelper(null, c);
    }

    /**
     * Returns a helper for the given class, either from the cache
     * or by creating a new instance.
     *
     * The method will make sure the helper will be cleaned up at the end of
     * the project, and only one instance will be created for each class.
     *
     * @param p the project instance. Can be null, in which case the helper is not cached.
     * @param c The class for which a helper is required.
     *          Must not be <code>null</code>.
     *
     * @return a helper for the specified class
     */
    public static synchronized IntrospectionHelper getHelper(final Project p, final Class<?> c) {
        IntrospectionHelper ih = HELPERS.get(c.getName());
        // If a helper cannot be found, or if the helper is for another
        // classloader, create a new IH
        if (ih == null || ih.bean != c) {
            ih = new IntrospectionHelper(c);
            if (p != null) {
                // #30162: do *not* cache this if there is no project, as we
                // cannot guarantee that the cache will be cleared.
                HELPERS.put(c.getName(), ih);
            }
        }
        return ih;
    }

    /**
     * Sets the named attribute in the given element, which is part of the
     * given project.
     *
     * @param p The project containing the element. This is used when files
     *          need to be resolved. Must not be <code>null</code>.
     * @param element The element to set the attribute in. Must not be
     *                <code>null</code>.
     * @param attributeName The name of the attribute to set. Must not be
     *                      <code>null</code>.
     * @param value The value to set the attribute to. This may be interpreted
     *              or converted to the necessary type if the setter method
     *              doesn't accept an object of the supplied type.
     *
     * @exception BuildException if the introspected class doesn't support
     *                           the given attribute, or if the setting
     *                           method fails.
     */
    public void setAttribute(final Project p, final Object element, final String attributeName,
            final Object value) throws BuildException {
        final AttributeSetter as = attributeSetters.get(
                attributeName.toLowerCase(Locale.ENGLISH));
        if (as == null && value != null) {
            if (element instanceof DynamicAttributeNS) {
                final DynamicAttributeNS dc = (DynamicAttributeNS) element;
                final String uriPlusPrefix = ProjectHelper.extractUriFromComponentName(attributeName);
                final String uri = ProjectHelper.extractUriFromComponentName(uriPlusPrefix);
                final String localName = ProjectHelper.extractNameFromComponentName(attributeName);
                final String qName = uri.isEmpty() ? localName : uri + ":" + localName;
                dc.setDynamicAttribute(uri, localName, qName, value.toString());
                return;
            }
            if (element instanceof DynamicObjectAttribute) {
                final DynamicObjectAttribute dc = (DynamicObjectAttribute) element;
                dc.setDynamicAttribute(attributeName.toLowerCase(Locale.ENGLISH), value);
                return;
            }
            if (element instanceof DynamicAttribute) {
                final DynamicAttribute dc = (DynamicAttribute) element;
                dc.setDynamicAttribute(attributeName.toLowerCase(Locale.ENGLISH), value.toString());
                return;
            }
            if (attributeName.contains(":")) {
                return; // Ignore attribute from unknown uri's
            }
            final String msg = getElementName(p, element)
                    + " doesn't support the \"" + attributeName + "\" attribute.";
            throw new UnsupportedAttributeException(msg, attributeName);
        }
        if (as != null) { // possible if value == null
            try {
                as.setObject(p, element, value);
            } catch (final IllegalAccessException ie) {
                // impossible as getMethods should only return public methods
                throw new BuildException(ie);
            } catch (final InvocationTargetException ite) {
                throw extractBuildException(ite);
            }
        }
    }

    /**
     * Sets the named attribute in the given element, which is part of the
     * given project.
     *
     * @param p The project containing the element. This is used when files
     *          need to be resolved. Must not be <code>null</code>.
     * @param element The element to set the attribute in. Must not be
     *                <code>null</code>.
     * @param attributeName The name of the attribute to set. Must not be
     *                      <code>null</code>.
     * @param value The value to set the attribute to. This may be interpreted
     *              or converted to the necessary type if the setter method
     *              doesn't just take a string. Must not be <code>null</code>.
     *
     * @exception BuildException if the introspected class doesn't support
     *                           the given attribute, or if the setting
     *                           method fails.
     */
    public void setAttribute(final Project p, final Object element, final String attributeName,
                             final String value) throws BuildException {
        setAttribute(p, element, attributeName, (Object) value);
    }

    /**
     * Adds PCDATA to an element, using the element's
     * <code>void addText(String)</code> method, if it has one. If no
     * such method is present, a BuildException is thrown if the
     * given text contains non-whitespace.
     *
     * @param project The project which the element is part of.
     *                Must not be <code>null</code>.
     * @param element The element to add the text to.
     *                Must not be <code>null</code>.
     * @param text    The text to add.
     *                Must not be <code>null</code>.
     *
     * @exception BuildException if non-whitespace text is provided and no
     *                           method is available to handle it, or if
     *                           the handling method fails.
     */
    public void addText(final Project project, final Object element, String text)
        throws BuildException {
        if (addText == null) {
            text = text.trim();
            // Element doesn't handle text content
            if (text.isEmpty()) {
                // Only whitespace - ignore
                return;
            }
            // Not whitespace - fail
            throw new BuildException(project.getElementName(element)
                    + " doesn't support nested text data (\"" + condenseText(text) + "\").");
        }
        try {
            addText.invoke(element, text);
        } catch (final IllegalAccessException ie) {
            // impossible as getMethods should only return public methods
            throw new BuildException(ie);
        } catch (final InvocationTargetException ite) {
            throw extractBuildException(ite);
        }
    }

    /**
     * part of the error message created by {@link #throwNotSupported
     * throwNotSupported}.
     * @since Ant 1.8.0
     */
    protected static final String NOT_SUPPORTED_CHILD_PREFIX =
        " doesn't support the nested \"";

    /**
     * part of the error message created by {@link #throwNotSupported
     * throwNotSupported}.
     * @since Ant 1.8.0
     */
    protected static final String NOT_SUPPORTED_CHILD_POSTFIX = "\" element.";

    /**
     * Utility method to throw a NotSupported exception
     *
     * @param project the Project instance.
     * @param parent the object which doesn't support a requested element
     * @param elementName the name of the Element which is trying to be created.
     */
    public void throwNotSupported(final Project project, final Object parent, final String elementName) {
        final String msg = project.getElementName(parent)
            + NOT_SUPPORTED_CHILD_PREFIX + elementName
            + NOT_SUPPORTED_CHILD_POSTFIX;
        throw new UnsupportedElementException(msg, elementName);
    }

    /**
     * Get the specific NestedCreator for a given project/parent/element combination
     * @param project ant project
     * @param parentUri URI of the parent.
     * @param parent the parent class
     * @param elementName element to work with. This can contain
     *  a URI,localname tuple of of the form uri:localname
     * @param child the bit of XML to work with
     * @return a nested creator that can handle the child elements.
     * @throws BuildException if the parent does not support child elements of that name
     */
    private NestedCreator getNestedCreator(
        final Project project, String parentUri, final Object parent,
        final String elementName, final UnknownElement child) throws BuildException {

        String uri = ProjectHelper.extractUriFromComponentName(elementName);
        final String name = ProjectHelper.extractNameFromComponentName(elementName);

        if (uri.equals(ProjectHelper.ANT_CORE_URI)) {
            uri = "";
        }
        if (parentUri.equals(ProjectHelper.ANT_CORE_URI)) {
            parentUri = "";
        }
        NestedCreator nc = null;
        if (uri.equals(parentUri) || uri.isEmpty()) {
            nc = nestedCreators.get(name.toLowerCase(Locale.ENGLISH));
        }
        if (nc == null) {
            nc = createAddTypeCreator(project, parent, elementName);
        }
        if (nc == null
                && (parent instanceof DynamicElementNS || parent instanceof DynamicElement)) {
            final String qName = child == null ? name : child.getQName();
            final Object nestedElement = createDynamicElement(parent,
                    child == null ? "" : child.getNamespace(), name, qName);
            if (nestedElement != null) {
                nc = new NestedCreator(null) {
                    @Override
                    Object create(final Project project, final Object parent, final Object ignore) {
                        return nestedElement;
                    }
                };
            }
        }
        if (nc == null) {
            throwNotSupported(project, parent, elementName);
        }
        return nc;
    }

    /**
     * Invokes the "correct" createDynamicElement method on parent in
     * order to obtain a child element by name.
     *
     * @since Ant 1.8.0.
     */
    private Object createDynamicElement(final Object parent, final String ns,
                                        final String localName, final String qName) {
        Object nestedElement = null;
        if (parent instanceof DynamicElementNS) {
            final DynamicElementNS dc = (DynamicElementNS) parent;
            nestedElement = dc.createDynamicElement(ns, localName, qName);
        }
        if (nestedElement == null && parent instanceof DynamicElement) {
            final DynamicElement dc = (DynamicElement) parent;
            nestedElement =
                dc.createDynamicElement(localName.toLowerCase(Locale.ENGLISH));
        }
        return nestedElement;
    }

    /**
     * Creates a named nested element. Depending on the results of the
     * initial introspection, either a method in the given parent instance
     * or a simple no-arg constructor is used to create an instance of the
     * specified element type.
     *
     * @param project Project to which the parent object belongs.
     *                Must not be <code>null</code>. If the resulting
     *                object is an instance of ProjectComponent, its
     *                Project reference is set to this parameter value.
     * @param parent  Parent object used to create the instance.
     *                Must not be <code>null</code>.
     * @param elementName Name of the element to create an instance of.
     *                    Must not be <code>null</code>.
     *
     * @return an instance of the specified element type
     * @deprecated since 1.6.x.
     *             This is not a namespace aware method.
     *
     * @exception BuildException if no method is available to create the
     *                           element instance, or if the creating method fails.
     */
    @Deprecated
    public Object createElement(final Project project, final Object parent, final String elementName)
            throws BuildException {
        final NestedCreator nc = getNestedCreator(project, "", parent, elementName, null);
        try {
            final Object nestedElement = nc.create(project, parent, null);
            if (project != null) {
                project.setProjectReference(nestedElement);
            }
            return nestedElement;
        } catch (final IllegalAccessException | InstantiationException ie) {
            // impossible as getMethods should only return public methods
            throw new BuildException(ie);
        } catch (final InvocationTargetException ite) {
            throw extractBuildException(ite);
        }
    }

    /**
     * returns an object that creates and stores an object
     * for an element of a parent.
     *
     * @param project      Project to which the parent object belongs.
     * @param parentUri    The namespace uri of the parent object.
     * @param parent       Parent object used to create the creator object to
     *                     create and store and instance of a subelement.
     * @param elementName  Name of the element to create an instance of.
     * @param ue           The unknown element associated with the element.
     * @return a creator object to create and store the element instance.
     */
    public Creator getElementCreator(
        final Project project, final String parentUri, final Object parent, final String elementName, final UnknownElement ue) {
        final NestedCreator nc = getNestedCreator(project, parentUri, parent, elementName, ue);
        return new Creator(project, parent, nc);
    }

    /**
     * Indicates whether the introspected class is a dynamic one,
     * supporting arbitrary nested elements and/or attributes.
     *
     * @return <div><code>true</code> if the introspected class is dynamic;
     *         <code>false</code> otherwise.</div>
     * @since Ant 1.6.3
     *
     * @see DynamicElement
     * @see DynamicElementNS
     */
    public boolean isDynamic() {
        return DynamicElement.class.isAssignableFrom(bean)
                || DynamicElementNS.class.isAssignableFrom(bean);
    }

    /**
     * Indicates whether the introspected class is a task container,
     * supporting arbitrary nested tasks/types.
     *
     * @return <code>true</code> if the introspected class is a container;
     *         <code>false</code> otherwise.
     * @since Ant 1.6.3
     *
     * @see TaskContainer
     */
    public boolean isContainer() {
        return TaskContainer.class.isAssignableFrom(bean);
    }

    /**
     * Indicates if this element supports a nested element of the
     * given name.
     *
     * @param elementName the name of the nested element being checked
     *
     * @return true if the given nested element is supported
     */
    public boolean supportsNestedElement(final String elementName) {
        return supportsNestedElement("", elementName);
    }

    /**
     * Indicate if this element supports a nested element of the
     * given name.
     *
     * <p>Note that this method will always return true if the
     * introspected class is {@link #isDynamic dynamic} or contains a
     * method named "add" with void return type and a single argument.
     * To ge a more thorough answer, use the four-arg version of this
     * method instead.</p>
     *
     * @param parentUri   the uri of the parent
     * @param elementName the name of the nested element being checked
     *
     * @return true if the given nested element is supported
     */
    public boolean supportsNestedElement(final String parentUri, final String elementName) {
        return isDynamic() || !addTypeMethods.isEmpty()
                || supportsReflectElement(parentUri, elementName);
    }

    /**
     * Indicate if this element supports a nested element of the
     * given name.
     *
     * <p>Note that this method will always return true if the
     * introspected class is {@link #isDynamic dynamic}, so be
     * prepared to catch an exception about unsupported children when
     * calling {@link #getElementCreator getElementCreator}.</p>
     *
     * @param parentUri   the uri of the parent
     * @param elementName the name of the nested element being checked
     * @param project currently executing project instance
     * @param parent the parent element
     *
     * @return true if the given nested element is supported
     * @since Ant 1.8.0.
     */
    public boolean supportsNestedElement(final String parentUri, final String elementName,
                                         final Project project, final Object parent) {
        return !addTypeMethods.isEmpty()
                && createAddTypeCreator(project, parent, elementName) != null
                || isDynamic() || supportsReflectElement(parentUri, elementName);
    }

    /**
     * Check if this element supports a nested element from reflection.
     *
     * @param parentUri   the uri of the parent
     * @param elementName the name of the nested element being checked
     *
     * @return true if the given nested element is supported
     * @since Ant 1.8.0
     */
    public boolean supportsReflectElement(
        String parentUri, final String elementName) {
        final String name = ProjectHelper.extractNameFromComponentName(elementName);
        if (!nestedCreators.containsKey(name.toLowerCase(Locale.ENGLISH))) {
            return false;
        }
        String uri = ProjectHelper.extractUriFromComponentName(elementName);
        if (uri.equals(ProjectHelper.ANT_CORE_URI) || uri.isEmpty()) {
            return true;
        }
        if (parentUri.equals(ProjectHelper.ANT_CORE_URI)) {
            parentUri = "";
        }
        return uri.equals(parentUri);
    }

    /**
     * Stores a named nested element using a storage method determined
     * by the initial introspection. If no appropriate storage method
     * is available, this method returns immediately.
     *
     * @param project Ignored in this implementation.
     *                May be <code>null</code>.
     *
     * @param parent  Parent instance to store the child in.
     *                Must not be <code>null</code>.
     *
     * @param child   Child instance to store in the parent.
     *                Should not be <code>null</code>.
     *
     * @param elementName  Name of the child element to store.
     *                     May be <code>null</code>, in which case
     *                     this method returns immediately.
     *
     * @exception BuildException if the storage method fails.
     */
    public void storeElement(final Project project, final Object parent, final Object child,
        final String elementName) throws BuildException {
        if (elementName == null) {
            return;
        }
        final NestedCreator ns = nestedCreators.get(elementName.toLowerCase(Locale.ENGLISH));
        if (ns == null) {
            return;
        }
        try {
            ns.store(parent, child);
        } catch (final IllegalAccessException | InstantiationException ie) {
            // impossible as getMethods should only return public methods
            throw new BuildException(ie);
        } catch (final InvocationTargetException ite) {
            throw extractBuildException(ite);
        }
    }

    /**
     * Helper method to extract the inner fault from an {@link InvocationTargetException}, and turn
     * it into a BuildException. If it is already a BuildException, it is type cast and returned; if
     * not a new BuildException is created containing the child as nested text.
     * @param ite the exception
     * @return the nested exception
     */
    private static BuildException extractBuildException(final InvocationTargetException ite) {
        final Throwable t = ite.getTargetException();
        if (t instanceof BuildException) {
            return (BuildException) t;
        }
        return new BuildException(t);
    }

    /**
     * Returns the type of a named nested element.
     *
     * @param elementName The name of the element to find the type of.
     *                    Must not be <code>null</code>.
     *
     * @return the type of the nested element with the specified name.
     *         This will never be <code>null</code>.
     *
     * @exception BuildException if the introspected class does not
     *                           support the named nested element.
     */
    public Class<?> getElementType(final String elementName) throws BuildException {
        final Class<?> nt = nestedTypes.get(elementName);
        if (nt == null) {
            throw new UnsupportedElementException("Class "
                    + bean.getName() + " doesn't support the nested \""
                    + elementName + "\" element.", elementName);
        }
        return nt;
    }

    /**
     * Returns the type of a named attribute.
     *
     * @param attributeName The name of the attribute to find the type of.
     *                      Must not be <code>null</code>.
     *
     * @return the type of the attribute with the specified name.
     *         This will never be <code>null</code>.
     *
     * @exception BuildException if the introspected class does not
     *                           support the named attribute.
     */
    public Class<?> getAttributeType(final String attributeName) throws BuildException {
        final Class<?> at = attributeTypes.get(attributeName);
        if (at == null) {
            throw new UnsupportedAttributeException("Class "
                    + bean.getName() + " doesn't support the \""
                    + attributeName + "\" attribute.", attributeName);
        }
        return at;
    }

    /**
     * Returns the addText method when the introspected
     * class supports nested text.
     *
     * @return the method on this introspected class that adds nested text.
     *         Cannot be <code>null</code>.
     * @throws BuildException if the introspected class does not
     *         support the nested text.
     * @since Ant 1.6.3
     */
    public Method getAddTextMethod() throws BuildException {
        if (!supportsCharacters()) {
            throw new BuildException("Class " + bean.getName()
                    + " doesn't support nested text data.");
        }
        return addText;
    }

    /**
     * Returns the adder or creator method of a named nested element.
     *
     * @param  elementName The name of the attribute to find the setter
     *         method of. Must not be <code>null</code>.
     * @return the method on this introspected class that adds or creates this
     *         nested element. Can be <code>null</code> when the introspected
     *         class is a dynamic configurator!
     * @throws BuildException if the introspected class does not
     *         support the named nested element.
     * @since Ant 1.6.3
     */
    public Method getElementMethod(final String elementName) throws BuildException {
        final NestedCreator creator = nestedCreators.get(elementName);
        if (creator == null) {
            throw new UnsupportedElementException("Class "
                    + bean.getName() + " doesn't support the nested \""
                    + elementName + "\" element.", elementName);
        }
        return creator.method;
    }

    /**
     * Returns the setter method of a named attribute.
     *
     * @param  attributeName The name of the attribute to find the setter
     *         method of. Must not be <code>null</code>.
     * @return the method on this introspected class that sets this attribute.
     *         This will never be <code>null</code>.
     * @throws BuildException if the introspected class does not
     *         support the named attribute.
     * @since Ant 1.6.3
     */
    public Method getAttributeMethod(final String attributeName) throws BuildException {
        final AttributeSetter setter = attributeSetters.get(attributeName);
        if (setter == null) {
            throw new UnsupportedAttributeException("Class "
                    + bean.getName() + " doesn't support the \""
                    + attributeName + "\" attribute.", attributeName);
        }
        return setter.method;
    }

    /**
     * Returns whether or not the introspected class supports PCDATA.
     *
     * @return whether or not the introspected class supports PCDATA.
     */
    public boolean supportsCharacters() {
        return addText != null;
    }

    /**
     * Returns an enumeration of the names of the attributes supported by the introspected class.
     *
     * @return an enumeration of the names of the attributes supported by the introspected class.
     * @see #getAttributeMap
     */
    public Enumeration<String> getAttributes() {
        return Collections.enumeration(attributeSetters.keySet());
    }

    /**
     * Returns a read-only map of attributes supported by the introspected class.
     *
     * @return an attribute name to attribute <code>Class</code>
     *         unmodifiable map. Can be empty, but never <code>null</code>.
     * @since Ant 1.6.3
     */
    public Map<String, Class<?>> getAttributeMap() {
        return attributeTypes.isEmpty()
            ? Collections.emptyMap() : Collections.unmodifiableMap(attributeTypes);
    }

    /**
     * Returns an enumeration of the names of the nested elements supported
     * by the introspected class.
     *
     * @return an enumeration of the names of the nested elements supported
     *         by the introspected class.
     * @see #getNestedElementMap
     */
    public Enumeration<String> getNestedElements() {
        return Collections.enumeration(nestedTypes.keySet());
    }

    /**
     * Returns a read-only map of nested elements supported
     * by the introspected class.
     *
     * @return a nested-element name to nested-element <code>Class</code>
     *         unmodifiable map. Can be empty, but never <code>null</code>.
     * @since Ant 1.6.3
     */
    public Map<String, Class<?>> getNestedElementMap() {
        return nestedTypes.isEmpty()
            ? Collections.emptyMap() : Collections.unmodifiableMap(nestedTypes);
    }

    /**
     * Returns a read-only list of extension points supported
     * by the introspected class.
     * <p>
     * A task/type or nested element with void methods named <code>add()</code>
     * or <code>addConfigured()</code>, taking a single class or interface
     * argument, supports extensions point. This method returns the list of
     * all these <em>void add[Configured](type)</em> methods.
     *
     * @return a list of void, single argument add() or addConfigured()
     *         <code>Method</code>s of all supported extension points.
     *         These methods are sorted such that if the argument type of a
     *         method derives from another type also an argument of a method
     *         of this list, the method with the most derived argument will
     *         always appear first. Can be empty, but never <code>null</code>.
     * @since Ant 1.6.3
     */
    public List<Method> getExtensionPoints() {
        return addTypeMethods.isEmpty()
                ? Collections.emptyList() : Collections.unmodifiableList(addTypeMethods);
    }

    /**
     * Creates an implementation of AttributeSetter for the given
     * attribute type. Conversions (where necessary) are automatically
     * made for the following types:
     * <ul>
     * <li>String (left as it is)
     * <li>Character/char (first character is used)
     * <li>Boolean/boolean
     * ({@link Project#toBoolean(String) Project.toBoolean(String)} is used)
     * <li>Class (Class.forName is used)
     * <li>File (resolved relative to the appropriate project)
     * <li>Path (resolve relative to the appropriate project)
     * <li>Resource (resolved as a FileResource relative to the appropriate project)
     * <li>FileProvider (resolved as a FileResource relative to the appropriate project)
     * <li>EnumeratedAttribute (uses its own
     * {@link EnumeratedAttribute#setValue(String) setValue} method)
     * <li>Other primitive types (wrapper classes are used with constructors
     * taking String)
     * </ul>
     *
     * If none of the above covers the given parameters, a constructor for the
     * appropriate class taking a String parameter is used if it is available.
     *
     * @param m The method to invoke on the bean when the setter is invoked.
     *          Must not be <code>null</code>.
     * @param arg The type of the single argument of the bean's method.
     *            Must not be <code>null</code>.
     * @param attrName the name of the attribute for which the setter is being
     *                 created.
     *
     * @return an appropriate AttributeSetter instance, or <code>null</code>
     *         if no appropriate conversion is available.
     */
    private AttributeSetter createAttributeSetter(final Method m,
                                                  final Class<?> arg,
                                                  final String attrName) {
        // use wrappers for primitive classes, e.g. int and
        // Integer are treated identically
        final Class<?> reflectedArg = PRIMITIVE_TYPE_MAP.getOrDefault(arg, arg);

        // Object.class - it gets handled differently by AttributeSetter
        if (java.lang.Object.class == reflectedArg) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException,
                    IllegalAccessException {
                    throw new BuildException(
                        "Internal ant problem - this should not get called");
                }
            };
        }
        // simplest case - setAttribute expects String
        if (String.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException {
                    m.invoke(parent, (Object[]) new String[] {value});
                }
            };
        }
        // char and Character get special treatment - take the first character
        if (java.lang.Character.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException {
                    if (value.isEmpty()) {
                        throw new BuildException("The value \"\" is not a "
                                + "legal value for attribute \"" + attrName + "\"");
                    }
                    m.invoke(parent, (Object[]) new Character[] {value.charAt(0)});
                }
            };
        }
        // boolean and Boolean get special treatment because we have a nice method in Project
        if (java.lang.Boolean.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException {
                    m.invoke(parent, (Object[]) new Boolean[] {
                            Project.toBoolean(value) ? Boolean.TRUE : Boolean.FALSE });
                }
            };
        }
        // Class doesn't have a String constructor but a decent factory method
        if (java.lang.Class.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException, BuildException {
                    try {
                        m.invoke(parent, Class.forName(value));
                    } catch (final ClassNotFoundException ce) {
                        throw new BuildException(ce);
                    }
                }
            };
        }
        // resolve relative paths through Project
        if (java.io.File.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException {
                    m.invoke(parent, p.resolveFile(value));
                }
            };
        }
        // resolve relative nio paths through Project
        if (java.nio.file.Path.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException {
                    m.invoke(parent, p.resolveFile(value).toPath());
                }
            };
        }

        // resolve Resources/FileProviders as FileResources relative to Project:
        if (Resource.class.equals(reflectedArg) || FileProvider.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException, BuildException {
                    m.invoke(parent, new FileResource(p, p.resolveFile(value)));
                }
            };
        }
        // EnumeratedAttributes have their own helper class
        if (EnumeratedAttribute.class.isAssignableFrom(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException, BuildException {
                    try {
                        final EnumeratedAttribute ea =
                                (EnumeratedAttribute) reflectedArg.getDeclaredConstructor().newInstance();
                        ea.setValue(value);
                        m.invoke(parent, ea);
                    } catch (final InstantiationException | NoSuchMethodException ie) {
                        throw new BuildException(ie);
                    }
                }
            };
        }

        final AttributeSetter setter = getEnumSetter(reflectedArg, m, arg);
        if (setter != null) {
            return setter;
        }

        if (java.lang.Long.class.equals(reflectedArg)) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                        throws InvocationTargetException, IllegalAccessException, BuildException {
                    try {
                        m.invoke(parent, StringUtils.parseHumanSizes(value));
                    } catch (final NumberFormatException e) {
                        throw new BuildException("Can't assign non-numeric"
                                                 + " value '" + value + "' to"
                                                 + " attribute " + attrName);
                    } catch (final InvocationTargetException | IllegalAccessException e) {
                        throw e;
                    } catch (final Exception e) {
                        throw new BuildException(e);
                    }
                }
            };
        }
        // worst case. look for a public String constructor and use it
        // also supports new Whatever(Project, String) as for Path or Reference
        // This is used (deliberately) for all primitives/wrappers other than
        // char, boolean, and long.
        boolean includeProject;
        Constructor<?> c;
        try {
            // First try with Project.
            c = reflectedArg.getConstructor(Project.class, String.class);
            includeProject = true;
        } catch (final NoSuchMethodException nme) {
            // OK, try without.
            try {
                c = reflectedArg.getConstructor(String.class);
                includeProject = false;
            } catch (final NoSuchMethodException nme2) {
                // Well, no matching constructor.
                return null;
            }
        }
        final boolean finalIncludeProject = includeProject;
        final Constructor<?> finalConstructor = c;

        return new AttributeSetter(m, arg) {
            @Override
            public void set(final Project p, final Object parent, final String value)
                    throws InvocationTargetException, IllegalAccessException, BuildException {
                try {
                    final Object[] args = finalIncludeProject
                            ? new Object[] {p, value} : new Object[] {value};

                    final Object attribute = finalConstructor.newInstance(args);
                    if (p != null) {
                        p.setProjectReference(attribute);
                    }
                    m.invoke(parent, attribute);
                } catch (final InvocationTargetException e) {
                    final Throwable cause = e.getCause();
                    if (cause instanceof IllegalArgumentException) {
                        throw new BuildException("Can't assign value '" + value
                                                 + "' to attribute " + attrName
                                                 + ", reason: "
                                                 + cause.getClass()
                                                 + " with message '"
                                                 + cause.getMessage() + "'");
                    }
                    throw e;
                } catch (final InstantiationException ie) {
                    throw new BuildException(ie);
                }
            }
        };
    }

    private AttributeSetter getEnumSetter(
        final Class<?> reflectedArg, final Method m, final Class<?> arg) {
        if (reflectedArg.isEnum()) {
            return new AttributeSetter(m, arg) {
                @Override
                public void set(final Project p, final Object parent, final String value)
                    throws InvocationTargetException, IllegalAccessException,
                    BuildException {
                    Enum<?> setValue;
                    try {
                        @SuppressWarnings({ "unchecked", "rawtypes" })
                        final Enum<?> enumValue = Enum.valueOf((Class<? extends Enum>) reflectedArg,
                                value);
                        setValue = enumValue;
                    } catch (final IllegalArgumentException e) {
                        // there is a specific logic here for the value
                        // being out of the allowed set of enumerations.
                        throw new BuildException("'" + value + "' is not a permitted value for "
                                + reflectedArg.getName());
                    }
                    m.invoke(parent, setValue);
                }
            };
        }
        return null;
    }

    /**
     * Returns a description of the type of the given element in
     * relation to a given project. This is used for logging purposes
     * when the element is asked to cope with some data it has no way of handling.
     *
     * @param project The project the element is defined in. Must not be <code>null</code>.
     *
     * @param element The element to describe. Must not be <code>null</code>.
     *
     * @return a description of the element type
     */
    private String getElementName(final Project project, final Object element) {
        return project.getElementName(element);
    }

    /**
     * Extracts the name of a property from a method name by subtracting
     * a given prefix and converting into lower case. It is up to calling
     * code to make sure the method name does actually begin with the
     * specified prefix - no checking is done in this method.
     *
     * @param methodName The name of the method in question. Must not be <code>null</code>.
     * @param prefix     The prefix to remove. Must not be <code>null</code>.
     *
     * @return the lower-cased method name with the prefix removed.
     */
    private static String getPropertyName(final String methodName, final String prefix) {
        return methodName.substring(prefix.length()).toLowerCase(Locale.ENGLISH);
    }

    /**
     * creator - allows use of create/store external
     * to IntrospectionHelper.
     * The class is final as it has a private constructor.
     */
    public static final class Creator {
        private final NestedCreator nestedCreator;
        private final Object parent;
        private final Project project;
        private Object nestedObject;
        private String polyType;

        /**
         * Creates a new Creator instance.
         * This object is given to the UnknownElement to create
         * objects for sub-elements. UnknownElement calls
         * create to create an object, the object then gets
         * configured and then UnknownElement calls store.
         * SetPolyType may be used to override the type used
         * to create the object with. SetPolyType gets called before create.
         *
         * @param project the current project
         * @param parent  the parent object to create the object in
         * @param nestedCreator the nested creator object to use
         */
        private Creator(final Project project, final Object parent, final NestedCreator nestedCreator) {
            this.project = project;
            this.parent = parent;
            this.nestedCreator = nestedCreator;
        }

        /**
         * Used to override the class used to create the object.
         *
         * @param polyType a ant component type name
         */
        public void setPolyType(final String polyType) {
            this.polyType = polyType;
        }

        /**
         * Create an object using this creator, which is determined by introspection.
         *
         * @return the created object
         */
        public Object create() {
            if (polyType != null) {
                if (!nestedCreator.isPolyMorphic()) {
                    throw new BuildException(
                            "Not allowed to use the polymorphic form for this element");
                }
                final ComponentHelper helper = ComponentHelper.getComponentHelper(project);
                nestedObject = helper.createComponent(polyType);
                if (nestedObject == null) {
                    throw new BuildException("Unable to create object of type " + polyType);
                }
            }
            try {
                nestedObject = nestedCreator.create(project, parent, nestedObject);
                if (project != null) {
                    project.setProjectReference(nestedObject);
                }
                return nestedObject;
            } catch (final IllegalAccessException | InstantiationException ex) {
                throw new BuildException(ex);
            } catch (final IllegalArgumentException ex) {
                if (polyType == null) {
                    throw ex;
                }
                throw new BuildException("Invalid type used " + polyType);
            } catch (final InvocationTargetException ex) {
                throw extractBuildException(ex);
            }
        }

        /**
         * @return the real object (used currently only for presetdef).
         */
        public Object getRealObject() {
            return nestedCreator.getRealObject();
        }

        /**
         * Stores the nested element object using a storage method determined by introspection.
         *
         */
        public void store() {
            try {
                nestedCreator.store(parent, nestedObject);
            } catch (final IllegalAccessException | InstantiationException ex) {
                throw new BuildException(ex);
            } catch (final IllegalArgumentException ex) {
                if (polyType == null) {
                    throw ex;
                }
                throw new BuildException("Invalid type used " + polyType);
            } catch (final InvocationTargetException ex) {
                throw extractBuildException(ex);
            }
        }
    }

    /**
     * Internal interface used to create nested elements. Not documented
     * in detail for reasons of source code readability.
     */
    private abstract static class NestedCreator {
        private final Method method; // the method called to add/create the nested element

        protected NestedCreator(final Method m) {
            method = m;
        }
        Method getMethod() {
            return method;
        }
        boolean isPolyMorphic() {
            return false;
        }
        Object getRealObject() {
            return null;
        }
        abstract Object create(Project project, Object parent, Object child)
                throws InvocationTargetException, IllegalAccessException, InstantiationException;

        void store(final Object parent, final Object child)
                 throws InvocationTargetException, IllegalAccessException, InstantiationException {
            // DO NOTHING
        }
    }

    private static class CreateNestedCreator extends NestedCreator {
        CreateNestedCreator(final Method m) {
            super(m);
        }

        @Override
        Object create(final Project project, final Object parent, final Object ignore)
                throws InvocationTargetException, IllegalAccessException {
            return getMethod().invoke(parent);
        }
    }

    /** Version to use for addXXX and addConfiguredXXX */
    private static class AddNestedCreator extends NestedCreator {

        static final int ADD = 1;
        static final int ADD_CONFIGURED = 2;

        private final Constructor<?> constructor;
        private final int behavior; // ADD or ADD_CONFIGURED

        AddNestedCreator(final Method m, final Constructor<?> c, final int behavior) {
            super(m);
            this.constructor = c;
            this.behavior = behavior;
        }

        @Override
        boolean isPolyMorphic() {
            return true;
        }

        @Override
        Object create(final Project project, final Object parent, Object child)
                throws InvocationTargetException, IllegalAccessException, InstantiationException {
            if (child == null) {
                child = constructor.newInstance(
                        constructor.getParameterTypes().length == 0
                                ? new Object[] {} : new Object[] {project});
            }
            if (child instanceof PreSetDef.PreSetDefinition) {
                child = ((PreSetDef.PreSetDefinition) child).createObject(project);
            }
            if (behavior == ADD) {
                istore(parent, child);
            }
            return child;
        }

        @Override
        void store(final Object parent, final Object child)
                throws InvocationTargetException, IllegalAccessException, InstantiationException {
            if (behavior == ADD_CONFIGURED) {
                istore(parent, child);
            }
        }

        private void istore(final Object parent, final Object child)
                throws InvocationTargetException, IllegalAccessException {
            getMethod().invoke(parent, child);
        }
    }

    /**
     * Internal interface used to setting element attributes. Not documented
     * in detail for reasons of source code readability.
     */
    private abstract static class AttributeSetter {
        private final Method method; // the method called to set the attribute
        private final Class<?> type;
        protected AttributeSetter(final Method m, final Class<?> type) {
            method = m;
            this.type = type;
        }
        void setObject(final Project p, final Object parent, final Object value)
                throws InvocationTargetException, IllegalAccessException, BuildException {
            if (type != null) {
                Class<?> useType = type;
                if (type.isPrimitive()) {
                    if (value == null) {
                        throw new BuildException(
                            "Attempt to set primitive "
                            + getPropertyName(method.getName(), "set")
                            + " to null on " + parent);
                    }
                    useType = PRIMITIVE_TYPE_MAP.get(type);
                }
                if (value == null || useType.isInstance(value)) {
                    method.invoke(parent, value);
                    return;
                }
            }
            set(p, parent, value.toString());
        }
        abstract void set(Project p, Object parent, String value)
                throws InvocationTargetException, IllegalAccessException, BuildException;
    }

    /**
     * Clears the static cache of on build finished.
     */
    public static synchronized void clearCache() {
        HELPERS.clear();
    }

    /**
     * Create a NestedCreator for the given element.
     * @param project owning project
     * @param parent Parent object used to create the instance.
     * @param elementName name of the element
     * @return a nested creator, or null if there is no component of the given name, or it
     *        has no matching add type methods
     * @throws BuildException if something goes wrong
     */
    private NestedCreator createAddTypeCreator(
            final Project project, final Object parent, final String elementName) throws BuildException {
        if (addTypeMethods.isEmpty()) {
            return null;
        }
        final ComponentHelper helper = ComponentHelper.getComponentHelper(project);

        final MethodAndObject restricted =  createRestricted(helper, elementName, addTypeMethods);
        final MethodAndObject topLevel = createTopLevel(helper, elementName, addTypeMethods);

        if (restricted == null && topLevel == null) {
            return null;
        }

        if (restricted != null && topLevel != null) {
            throw new BuildException(
                "ambiguous: type and component definitions for "
                + elementName);
        }

        final MethodAndObject methodAndObject = restricted == null ? topLevel : restricted;

        Object rObject = methodAndObject.object;
        if (methodAndObject.object instanceof PreSetDef.PreSetDefinition) {
            rObject = ((PreSetDef.PreSetDefinition) methodAndObject.object)
                .createObject(project);
        }
        final Object nestedObject = methodAndObject.object;
        final Object realObject = rObject;

        return new NestedCreator(methodAndObject.method) {
            @Override
            Object create(final Project project, final Object parent, final Object ignore)
                    throws InvocationTargetException, IllegalAccessException {
                if (!getMethod().getName().endsWith("Configured")) {
                    getMethod().invoke(parent, realObject);
                }
                return nestedObject;
            }

            @Override
            Object getRealObject() {
                return realObject;
            }

            @Override
            void store(final Object parent, final Object child) throws InvocationTargetException,
                    IllegalAccessException, InstantiationException {
                if (getMethod().getName().endsWith("Configured")) {
                    getMethod().invoke(parent, realObject);
                }
            }
        };
    }

    /**
     * Inserts an add or addConfigured method into
     * the addTypeMethods array. The array is
     * ordered so that the more derived classes are first.
     * If both add and addConfigured are present, the addConfigured will take priority.
     * @param method the <code>Method</code> to insert.
     */
    private void insertAddTypeMethod(final Method method) {
        final Class<?> argClass = method.getParameterTypes()[0];
        final int size = addTypeMethods.size();
        for (int c = 0; c < size; ++c) {
            final Method current = addTypeMethods.get(c);
            if (current.getParameterTypes()[0].equals(argClass)) {
                if ("addConfigured".equals(method.getName())) {
                    // add configured replaces the add method
                    addTypeMethods.set(c, method);
                }
                return; // Already present
            }
            if (current.getParameterTypes()[0].isAssignableFrom(argClass)) {
                addTypeMethods.add(c, method);
                return; // higher derived
            }
        }
        addTypeMethods.add(method);
    }

    /**
     * Search the list of methods to find the first method
     * that has a parameter that accepts the nested element object.
     * @param paramClass the <code>Class</code> type to search for.
     * @param methods the <code>List</code> of methods to search.
     * @return a matching <code>Method</code>; null if none found.
     */
    private Method findMatchingMethod(final Class<?> paramClass, final List<Method> methods) {
        if (paramClass == null) {
            return null;
        }
        Class<?> matchedClass = null;
        Method matchedMethod = null;

        for (final Method method : methods) {
            final Class<?> methodClass = method.getParameterTypes()[0];
            if (methodClass.isAssignableFrom(paramClass)) {
                if (matchedClass == null) {
                    matchedClass = methodClass;
                    matchedMethod = method;
                } else if (!methodClass.isAssignableFrom(matchedClass)) {
                    throw new BuildException("ambiguous: types " + matchedClass.getName() + " and "
                            + methodClass.getName() + " match " + paramClass.getName());
                }
            }
        }
        return matchedMethod;
    }

    private String condenseText(final String text) {
        if (text.length() <= MAX_REPORT_NESTED_TEXT) {
            return text;
        }
        final int ends = (MAX_REPORT_NESTED_TEXT - ELLIPSIS.length()) / 2;
        return new StringBuffer(text).replace(ends, text.length() - ends, ELLIPSIS).toString();
    }


    private static class MethodAndObject {
        private final Method method;
        private final Object object;
        public MethodAndObject(final Method method, final Object object) {
            this.method = method;
            this.object = object;
        }
    }

    /**
     *
     */
    private AntTypeDefinition findRestrictedDefinition(
        final ComponentHelper helper, final String componentName, final List<Method> methods) {
        AntTypeDefinition definition = null;
        Class<?> matchedDefinitionClass = null;

        final List<AntTypeDefinition> definitions = helper.getRestrictedDefinitions(componentName);
        if (definitions == null) {
            return null;
        }
        synchronized (definitions) {
            for (final AntTypeDefinition d : definitions) {
                final Class<?> exposedClass = d.getExposedClass(helper.getProject());
                if (exposedClass == null) {
                    continue;
                }
                final Method method = findMatchingMethod(exposedClass, methods);
                if (method == null) {
                    continue;
                }
                if (matchedDefinitionClass != null) {
                    throw new BuildException(
                        "ambiguous: restricted definitions for "
                        + componentName + " "
                        + matchedDefinitionClass + " and " + exposedClass);
                }
                matchedDefinitionClass = exposedClass;
                definition = d;
            }
        }
        return definition;
    }

    private MethodAndObject createRestricted(
        final ComponentHelper helper, final String elementName, final List<Method> addTypeMethods) {

        final Project project = helper.getProject();

        final AntTypeDefinition restrictedDefinition =
            findRestrictedDefinition(helper, elementName, addTypeMethods);

        if (restrictedDefinition == null) {
            return null;
        }

        final Method addMethod = findMatchingMethod(
            restrictedDefinition.getExposedClass(project), addTypeMethods);
        if (addMethod == null) {
            throw new BuildException("Ant Internal Error - contract mismatch for "
                    + elementName);
        }
        final Object addedObject = restrictedDefinition.create(project);
        if (addedObject == null) {
            throw new BuildException(
                "Failed to create object " + elementName
                + " of type " + restrictedDefinition.getTypeClass(project));
        }
        return new MethodAndObject(addMethod, addedObject);
    }

    private MethodAndObject createTopLevel(
        final ComponentHelper helper, final String elementName, final List<Method> methods) {
        final Class<?> clazz = helper.getComponentClass(elementName);
        if (clazz == null) {
            return null;
        }
        final Method addMethod = findMatchingMethod(clazz, addTypeMethods);
        if (addMethod == null) {
            return null;
        }
        final Object addedObject = helper.createComponent(elementName);
        return new MethodAndObject(addMethod, addedObject);
    }

}
