/*
 * 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 freemarker.ext.beans;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

import freemarker.core.BugException;
import freemarker.core._DelayedFTLTypeDescription;
import freemarker.core._DelayedShortClassName;
import freemarker.core._TemplateModelException;
import freemarker.ext.util.ModelCache;
import freemarker.ext.util.ModelFactory;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.log.Logger;
import freemarker.template.AdapterTemplateModel;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.ObjectWrapper;
import freemarker.template.ObjectWrapperAndUnwrapper;
import freemarker.template.SimpleObjectWrapper;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelAdapter;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;
import freemarker.template.Version;
import freemarker.template._TemplateAPI;
import freemarker.template._VersionInts;
import freemarker.template.utility.ClassUtil;
import freemarker.template.utility.RichObjectWrapper;
import freemarker.template.utility.WriteProtectable;

/**
 * {@link ObjectWrapper} that is able to expose the Java API of arbitrary Java objects. This is also the superclass of
 * {@link DefaultObjectWrapper}. Note that instances of this class generally should be created with a
 * {@link BeansWrapperBuilder}, not with its public constructors.
 * 
 * <p>
 * As of 2.3.22, using {@link BeansWrapper} unextended is not recommended. Instead, {@link DefaultObjectWrapper} with
 * its {@code incompatibleImprovements} property set to 2.3.22 (or higher) is the recommended {@link ObjectWrapper}.
 * 
 * <p>
 * This class is only thread-safe after you have finished calling its setter methods, and then safely published it (see
 * JSR 133 and related literature). When used as part of {@link Configuration}, of course it's enough if that was safely
 * published and then left unmodified. Using {@link BeansWrapperBuilder} also guarantees thread safety.
 */
public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
    private static final Logger LOG = Logger.getLogger("freemarker.beans");

    /**
     * @deprecated Use {@link ObjectWrapperAndUnwrapper#CANT_UNWRAP_TO_TARGET_CLASS} instead. It's not a public field
     *             anyway.
     */
    @Deprecated
    static final Object CAN_NOT_UNWRAP = ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
    
    /**
     * At this level of exposure, all methods and properties of the
     * wrapped objects are exposed to the template, and even the {@link MemberAccessPolicy}
     * is ignored.
     */
    public static final int EXPOSE_ALL = 0;
    
    /**
     * At this level of exposure, all methods and properties of the wrapped
     * objects are exposed to the template except methods that are deemed
     * not safe. The not safe methods are java.lang.Object methods wait() and
     * notify(), java.lang.Class methods getClassLoader() and newInstance(),
     * java.lang.reflect.Method and java.lang.reflect.Constructor invoke() and
     * newInstance() methods, all java.lang.reflect.Field set methods, all 
     * java.lang.Thread and java.lang.ThreadGroup methods that can change its 
     * state, as well as the usual suspects in java.lang.System and
     * java.lang.Runtime.
     *
     * <p>Note that the {@link MemberAccessPolicy} will further restrict what's visible. That mechanism was introduced
     * much later than "exposure levels", and it's the primary place to look at if you are concerned with safety.
     */
    public static final int EXPOSE_SAFE = 1;
    
    /**
     * At this level of exposure, only property getters are exposed.
     * Additionally, property getters that map to unsafe methods are not
     * exposed (i.e. Class.classLoader and Thread.contextClassLoader).
     *
     * <p>Note that the {@link MemberAccessPolicy} will further restrict what's visible.
     */
    public static final int EXPOSE_PROPERTIES_ONLY = 2;

    /**
     * At this level of exposure, no bean properties and methods are exposed.
     * Only map items, resource bundle items, and objects retrieved through
     * the generic get method (on objects of classes that have a generic get
     * method) can be retrieved through the hash interface. You might want to 
     * call {@link #setMethodsShadowItems(boolean)} with {@code false} value to
     * speed up map item retrieval.
     */
    public static final int EXPOSE_NOTHING = 3;

    // -----------------------------------------------------------------------------------------------------------------
    // Introspection cache:
    
    private final Object sharedIntrospectionLock;
    
    /** 
     * {@link Class} to class info cache.
     * This object is possibly shared with other {@link BeansWrapper}-s!
     * 
     * <p>To write this, always use {@link #replaceClassIntrospector(ClassIntrospectorBuilder)}.
     * 
     * <p>When reading this, it's good idea to synchronize on sharedInrospectionLock when it doesn't hurt overall
     * performance. In theory that's not needed, but apps might fail to keep the rules.
     */
    private ClassIntrospector classIntrospector;

    /**
     * {@link String} class name to {@link StaticModel} cache.
     * This object only belongs to a single {@link BeansWrapper}.
     * This has to be final as {@link #getStaticModels()} might return it any time and then it has to remain a good
     * reference.
     */
    private final StaticModels staticModels;
    
    /**
     * {@link String} class name to {@link EnumerationModel} cache.
     * This object only belongs to a single {@link BeansWrapper}.
     * This has to be final as {@link #getStaticModels()} might return it any time and then it has to remain a good
     * reference.
     */
    private final ClassBasedModelFactory enumModels;
    
    /**
     * Object to wrapped object cache; not used by default.
     * This object only belongs to a single {@link BeansWrapper}.
     */
    private final ModelCache modelCache;

    private final BooleanModel falseModel;
    private final BooleanModel trueModel;
    
    // -----------------------------------------------------------------------------------------------------------------

    // Why volatile: In principle it need not be volatile, but we want to catch modification attempts even if the
    // object was published improperly to other threads. After all, the main goal of WriteProtectable is protecting
    // things from buggy user code.
    private volatile boolean writeProtected;
    
    private TemplateModel nullModel = null;
    private int defaultDateType; // initialized from the BeansWrapperConfiguration
    private ObjectWrapper outerIdentity = this;
    private boolean methodsShadowItems = true;
    private boolean simpleMapWrapper;  // initialized from the BeansWrapperConfiguration
    private boolean strict;  // initialized from the BeansWrapperConfiguration
    private boolean preferIndexedReadMethod; // initialized from the BeansWrapperConfiguration

    private final Version incompatibleImprovements;


    /**
     * Creates a new instance with the incompatible-improvements-version specified in
     * {@link Configuration#DEFAULT_INCOMPATIBLE_IMPROVEMENTS}.
     * 
     * @deprecated Use {@link BeansWrapperBuilder} or, in rare cases, {@link #BeansWrapper(Version)} instead.
     */
    @Deprecated
    public BeansWrapper() {
        this(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // Attention! Don't change fields here, as the instance is possibly already visible to other threads.  
    }
    
    /**
     * Use {@link BeansWrapperBuilder} instead of the public constructors if possible.
     * The main disadvantage of using the public constructors is that the instances won't share caches. So unless having
     * a private cache is your goal, don't use them. See 
     * 
     * @param incompatibleImprovements
     *   Sets which of the non-backward-compatible improvements should be enabled. Not {@code null}. This version number
     *   is the same as the FreeMarker version number with which the improvements were implemented.
     *    
     *   <p>For new projects, it's recommended to set this to the FreeMarker version that's used during the development.
     *   For released products that are still actively developed it's a low risk change to increase the 3rd
     *   version number further as FreeMarker is updated, but of course you should always check the list of effects
     *   below. Increasing the 2nd or 1st version number possibly mean substantial changes with higher risk of breaking
     *   the application, but again, see the list of effects below.
     *   
     *   <p>The reason it's separate from {@link Configuration#setIncompatibleImprovements(Version)} is that
     *   {@link ObjectWrapper} objects are sometimes shared among multiple {@link Configuration}-s, so the two version
     *   numbers are technically independent. But it's recommended to keep those two version numbers the same. Actually,
     *   if you leave the {@link Configuration#setObjectWrapper(ObjectWrapper) object_wrapper} setting at its default
     *   (and most do), then that will be kept the same as of the {@link Configuration}.
     *
     *   <p>The changes enabled by {@code incompatibleImprovements} are (but also check the changes at
     *   {@link DefaultObjectWrapper#DefaultObjectWrapper(Version)}, if you are using {@link DefaultObjectWrapper}):
     *   <ul>
     *     <li>
     *       <p>2.3.0: No changes; this is the starting point, the version used in older projects.
     *     </li>
     *     <li>
     *       <p>2.3.21 (or higher):
     *       Several glitches were fixed in <em>overloaded</em> method selection. This usually just gets
     *       rid of errors (like ambiguity exceptions and numerical precision loses due to bad overloaded method
     *       choices), still, as in some cases the method chosen can be a different one now (that was the point of
     *       the reworking after all), it can mean a change in the behavior of the application. The most important
     *       change is that the treatment of {@code null} arguments were fixed, as earlier they were only seen
     *       applicable to parameters of type {@code Object}. Now {@code null}-s are seen to be applicable to any
     *       non-primitive parameters, and among those the one with the most specific type will be preferred (just
     *       like in Java), which is hence never the one with the {@code Object} parameter type. For more details
     *       about overloaded method selection changes see the version history in the FreeMarker Manual.
     *     </li>
     *     <li>
     *       <p>2.3.24 (or higher):
     *       {@link Iterator}-s were always said to be non-empty when using {@code ?has_content} and such (i.e.,
     *       operators that check emptiness without reading any elements). Now an {@link Iterator} counts as
     *       empty exactly if it has no elements left. (Note that this bug has never affected basic functionality, like
     *       {@code <#list ...>}.) 
     *     </li>  
     *     <li>
     *       <p>2.3.26 (or higher):
     *       The default of {@link BeansWrapper#getTreatDefaultMethodsAsBeanMembers()} changes from {@code false} to
     *       {@code true}. Thus, Java 8 default methods (and the bean properties they define) are exposed, despite that
     *       {@link java.beans.Introspector} (the official JavaBeans introspector) ignores them, at least as of Java 8. 
     *     </li>  
     *     <li>
     *       <p>2.3.27 (or higher):
     *       The default of the {@link #setPreferIndexedReadMethod(boolean) preferIndexedReadMethod} setting changes
     *       from {@code true} to {@code false}.
     *     </li>  
     *     <li>
     *       <p>2.3.33 (or higher):
     *       The default of {@link BeansWrapper#setRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy)}
     *       has changed to {@link ZeroArgumentNonVoidMethodPolicy#BOTH_PROPERTY_AND_METHOD}, from
     *       {@link ZeroArgumentNonVoidMethodPolicy#METHOD_ONLY}. This means that Java record public methods with
     *       0-arguments and non-void return type are now exposed both as properties, and as methods, while earlier they
     *       were only exposed as methods. That is, if in a record you have {@code public String name()}, now in
     *       templates the value can be accessed both as {@code obj.name} (like a property), and as {@code obj.name()}
     *       (for better backward compatibility only - it's bad style).
     *     </li>
     *   </ul>
     *   
     *   <p>Note that the version will be normalized to the lowest version where the same incompatible
     *   {@link BeansWrapper} improvements were already present, so {@link #getIncompatibleImprovements()} might return
     *   a lower version than what you have specified.
     *
     *   <p>Note again that most projects use {@link DefaultObjectWrapper} (which extends {@link BeansWrapper}), in
     *   which case see the additional changes at {@link DefaultObjectWrapper#DefaultObjectWrapper(Version)}!
     *   </p>
     *
     * @since 2.3.21
     */
    public BeansWrapper(Version incompatibleImprovements) {
        this(new BeansWrapperConfiguration(incompatibleImprovements) {}, false);
        // Attention! Don't don anything here, as the instance is possibly already visible to other threads through the
        // model factory callbacks.
    }
    
    private static volatile boolean ftmaDeprecationWarnLogged;
    
    /**
     * Same as {@link #BeansWrapper(BeansWrapperConfiguration, boolean, boolean)} with {@code true}
     * {@code finalizeConstruction} argument.
     * 
     * @since 2.3.21
     */
    protected BeansWrapper(BeansWrapperConfiguration bwConf, boolean writeProtected) {
        this(bwConf, writeProtected, true);
    }
    
    /**
     * Initializes the instance based on the {@link BeansWrapperConfiguration} specified.
     * 
     * @param writeProtected Makes the instance's configuration settings read-only via
     *     {@link WriteProtectable#writeProtect()}; this way it can use the shared class introspection cache.
     *     
     * @param finalizeConstruction Decides if the construction is finalized now, or the caller will do some more
     *     adjustments on the instance and then call {@link #finalizeConstruction(boolean)} itself. 
     * 
     * @since 2.3.22
     */
    protected BeansWrapper(BeansWrapperConfiguration bwConf, boolean writeProtected, boolean finalizeConstruction) {
        // Backward-compatibility hack for "finetuneMethodAppearance" overrides to work:
        if (bwConf.getMethodAppearanceFineTuner() == null) {
            Class<?> thisClass = this.getClass();
            boolean overridden = false;
            boolean testFailed = false;
            try {
                while (!overridden
                        && thisClass != DefaultObjectWrapper.class
                        && thisClass != BeansWrapper.class
                        && thisClass != SimpleObjectWrapper.class) {
                    try {
                        thisClass.getDeclaredMethod("finetuneMethodAppearance",
                                new Class<?>[] { Class.class, Method.class, MethodAppearanceDecision.class });
                        overridden = true;
                    } catch (NoSuchMethodException e) {
                        thisClass = thisClass.getSuperclass();
                    }
                }
            } catch (Throwable e) {
                // The security manager sometimes doesn't allow this
                LOG.info("Failed to check if finetuneMethodAppearance is overridden in " + thisClass.getName()
                        + "; acting like if it was, but this way it won't utilize the shared class introspection "
                        + "cache.",
                        e);
                overridden = true;
                testFailed = true;
            }
            if (overridden) {
                if (!testFailed && !ftmaDeprecationWarnLogged) {
                    LOG.warn("Overriding " + BeansWrapper.class.getName() + ".finetuneMethodAppearance is deprecated "
                            + "and will be banned sometimes in the future. Use setMethodAppearanceFineTuner instead.");
                    ftmaDeprecationWarnLogged = true;
                }
                bwConf = (BeansWrapperConfiguration) bwConf.clone(false);
                bwConf.setMethodAppearanceFineTuner(new MethodAppearanceFineTuner() {

                    @Override
                    public void process(
                            MethodAppearanceDecisionInput in, MethodAppearanceDecision out) {
                        BeansWrapper.this.finetuneMethodAppearance(in.getContainingClass(), in.getMethod(), out);
                    }
                    
                });
            }
        }
        
        this.incompatibleImprovements = bwConf.getIncompatibleImprovements();  // normalized
        
        simpleMapWrapper = bwConf.isSimpleMapWrapper();
        preferIndexedReadMethod =  bwConf.getPreferIndexedReadMethod();
        defaultDateType = bwConf.getDefaultDateType();
        outerIdentity = bwConf.getOuterIdentity() != null ? bwConf.getOuterIdentity() : this;
        strict = bwConf.isStrict();

        if (!writeProtected) {
            // As this is not a read-only BeansWrapper, the classIntrospector will be possibly replaced for a few times,
            // but we need to use the same sharedInrospectionLock forever, because that's what the model factories
            // synchronize on, even during the classIntrospector is being replaced.
            sharedIntrospectionLock = new Object();
            classIntrospector = new ClassIntrospector(
                    _BeansAPI.getClassIntrospectorBuilder(bwConf), sharedIntrospectionLock, false, false);
        } else {
            // As this is a read-only BeansWrapper, the classIntrospector is never replaced, and since it's shared by
            // other BeansWrapper instances, we use the lock belonging to the shared ClassIntrospector.
            classIntrospector = _BeansAPI.getClassIntrospectorBuilder(bwConf).build();
            sharedIntrospectionLock = classIntrospector.getSharedLock(); 
        }

        falseModel = new BooleanModel(Boolean.FALSE, this);
        trueModel = new BooleanModel(Boolean.TRUE, this);
        
        staticModels = new StaticModels(this);
        enumModels = new _EnumModels(this);
        modelCache = new BeansModelCache(this);
        setUseCache(bwConf.getUseModelCache());

        finalizeConstruction(writeProtected);
    }

    /**
     * Meant to be called after {@link BeansWrapper#BeansWrapper(BeansWrapperConfiguration, boolean, boolean)} when
     * its last argument was {@code false}; makes the instance read-only if necessary, then registers the model
     * factories in the class introspector. No further changes should be done after calling this, if
     * {@code writeProtected} was {@code true}. 
     * 
     * @since 2.3.22
     */
    protected void finalizeConstruction(boolean writeProtected) {
        if (writeProtected) {
            writeProtect();
        }
        
        // Attention! At this point, the BeansWrapper must be fully initialized, as when the model factories are
        // registered below, the BeansWrapper can immediately get concurrent callbacks. That those other threads will
        // see consistent image of the BeansWrapper is ensured that callbacks are always sync-ed on
        // classIntrospector.sharedLock, and so is classIntrospector.registerModelFactory(...).
        
        registerModelFactories();
    }
    
    /**
     * Makes the configuration properties (settings) of this {@link BeansWrapper} object read-only. As changing them
     * after the object has become visible to multiple threads leads to undefined behavior, it's recommended to call
     * this when you have finished configuring the object.
     * 
     * <p>Consider using {@link BeansWrapperBuilder} instead, which gives an instance that's already
     * write protected and also uses some shared caches/pools. 
     * 
     * @since 2.3.21
     */
    @Override
    public void writeProtect() {
        writeProtected = true;
    }

    /**
     * @since 2.3.21
     */
    @Override
    public boolean isWriteProtected() {
        return writeProtected;
    }
    
    Object getSharedIntrospectionLock() {
        return sharedIntrospectionLock;
    }
    
    /**
     * If this object is already read-only according to {@link WriteProtectable}, throws {@link IllegalStateException},
     * otherwise does nothing.
     * 
     * @since 2.3.21
     */
    protected void checkModifiable() {
        if (writeProtected) throw new IllegalStateException(
                "Can't modify the " + this.getClass().getName() + " object, as it was write protected.");
    }

    /**
     * @see #setStrict(boolean)
     */
    public boolean isStrict() {
    	return strict;
    }
    
    /**
     * Specifies if an attempt to read a bean property that doesn't exist in the
     * wrapped object should throw an {@link InvalidPropertyException}.
     * 
     * <p>If this property is {@code false} (the default) then an attempt to read
     * a missing bean property is the same as reading an existing bean property whose
     * value is {@code null}. The template can't tell the difference, and thus always
     * can use {@code ?default('something')} and {@code ?exists} and similar built-ins
     * to handle the situation.
     *
     * <p>If this property is {@code true} then an attempt to read a bean propertly in
     * the template (like {@code myBean.aProperty}) that doesn't exist in the bean
     * object (as opposed to just holding {@code null} value) will cause
     * {@link InvalidPropertyException}, which can't be suppressed in the template
     * (not even with {@code myBean.noSuchProperty?default('something')}). This way
     * {@code ?default('something')} and {@code ?exists} and similar built-ins can be used to
     * handle existing properties whose value is {@code null}, without the risk of
     * hiding typos in the property names. Typos will always cause error. But mind you, it
     * goes against the basic approach of FreeMarker, so use this feature only if you really
     * know what you are doing.
     */
    public void setStrict(boolean strict) {
        checkModifiable();
    	this.strict = strict;
    }

    /**
     * When wrapping an object, the BeansWrapper commonly needs to wrap
     * "sub-objects", for example each element in a wrapped collection.
     * Normally it wraps these objects using itself. However, this makes
     * it difficult to delegate to a BeansWrapper as part of a custom
     * aggregate ObjectWrapper. This method lets you set the ObjectWrapper
     * which will be used to wrap the sub-objects.
     * @param outerIdentity the aggregate ObjectWrapper
     */
    public void setOuterIdentity(ObjectWrapper outerIdentity) {
        checkModifiable();
        this.outerIdentity = outerIdentity;
    }

    /**
     * By default returns {@code this}.
     * @see #setOuterIdentity(ObjectWrapper)
     */
    public ObjectWrapper getOuterIdentity() {
        return outerIdentity;
    }

    /**
     * When set to {@code true}, the keys in {@link Map}-s won't mix with the method names when looking at them
     * from templates. The default is {@code false} for backward-compatibility, but is not recommended.
     * 
     * <p>When this is {@code false}, {@code myMap.foo} or {@code myMap['foo']} either returns the method {@code foo},
     * or calls {@code Map.get("foo")}. If both exists (the method and the {@link Map} key), one will hide the other,
     * depending on the {@link #isMethodsShadowItems()}, which default to {@code true} (the method
     * wins). Some frameworks use this so that you can call {@code myMap.get(nonStringKey)} from templates [*], but it
     * comes on the cost of polluting the key-set with the method names, and risking methods accidentally hiding
     * {@link Map} entries (or the other way around). Thus, this setup is not recommended.
     * (Technical note: {@link Map}-s will be wrapped into {@link MapModel} in this case.)  
     *
     * <p>When this is {@code true}, {@code myMap.foo} or {@code myMap['foo']} always calls {@code Map.get("foo")}.
     * The methods of the {@link Map} object aren't visible from templates in this case. This, however, spoils the
     * {@code myMap.get(nonStringKey)} workaround. But now you can use {@code myMap(nonStringKey)} instead, that is, you
     * can use the map itself as the {@code get} method. 
     * (Technical note: {@link Map}-s will be wrapped into {@link SimpleMapModel} in this case.)
     * 
     * <p>*: For historical reasons, FreeMarker 2.3.X doesn't support non-string keys with the {@code []} operator,
     *       hence the workarounds. This will be likely fixed in FreeMarker 2.4.0. Also note that the method- and
     *       the "field"-namespaces aren't separate in FreeMarker, hence {@code myMap.get} can return the {@code get}
     *       method.
     */
    public void setSimpleMapWrapper(boolean simpleMapWrapper) {
        checkModifiable();
        this.simpleMapWrapper = simpleMapWrapper;
    }

    /**
     * Tells whether Maps are exposed as simple maps, without access to their
     * method. See {@link #setSimpleMapWrapper(boolean)} for details.
     * @return true if Maps are exposed as simple hashes, false if they're
     * exposed as full JavaBeans.
     */
    public boolean isSimpleMapWrapper() {
        return simpleMapWrapper;
    }

    /**
     * Getter pair of {@link #setPreferIndexedReadMethod(boolean)} 
     * 
     * @since 2.3.27
     */
    public boolean getPreferIndexedReadMethod() {
        return preferIndexedReadMethod;
    }

    /**
     * Sets if when a JavaBean property has both a normal read method (like {@code String[] getFoos()}) and an indexed
     * read method (like {@code String getFoos(int index)}), and the Java {@link Introspector} exposes both (which only
     * happens since Java 8, apparently), which read method will be used when the property is accessed with the
     * shorthand syntax (like {@code myObj.foos}). Before {@link #getIncompatibleImprovements() incompatibleImprovements}
     * 2.3.27 it defaults to {@code true} for backward compatibility (although it's actually less backward compatible if
     * you are just switching to Java 8; see later), but the recommended value and the default starting with
     * {@link #getIncompatibleImprovements() incompatibleImprovements} 2.3.27 is {@code false}. This setting has no
     * effect on properties that only has normal read method, or only has indexed read method. In case a property has
     * both, using the indexed reader method is disadvantageous, as then FreeMarker can't tell what the highest allowed
     * index is, and so the property will be unlistable ({@code <#list foo as myObj.foos>} will fail).
     * 
     * <p>
     * Apparently, this setting only matters since Java 8, as before that {@link Introspector} did not expose the
     * indexed reader method if there was also a normal reader method. As with Java 8 the behavior of
     * {@link Introspector} has changed, some old templates started to break, as the property has suddenly become
     * unlistable (see earlier why). So setting this to {@code false} can be seen as a Java 8 compatibility fix.
     * 
     * @since 2.3.27
     */
    public void setPreferIndexedReadMethod(boolean preferIndexedReadMethod) {
        checkModifiable();
        this.preferIndexedReadMethod = preferIndexedReadMethod;
    }

    /**
     * Sets the method exposure level. By default, set to <code>EXPOSE_SAFE</code>.
     * @param exposureLevel can be any of the <code>EXPOSE_xxx</code>
     * constants.
     * Note that {@link #setMemberAccessPolicy(MemberAccessPolicy)} further restricts what's visible, unless this is
     * set to {@link #EXPOSE_ALL}.
     */
    public void setExposureLevel(int exposureLevel) {
        checkModifiable();
     
        if (classIntrospector.getExposureLevel() != exposureLevel) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setExposureLevel(exposureLevel);
            replaceClassIntrospector(builder);
        }
    }
    
    /**
     * @since 2.3.21
     */
    public int getExposureLevel() {
        return classIntrospector.getExposureLevel();
    }
    
    /**
     * Controls whether public instance fields of classes are exposed to 
     * templates.
     * @param exposeFields if set to true, public instance fields of classes 
     * that do not have a property getter defined can be accessed directly by
     * their name. If there is a property getter for a property of the same 
     * name as the field (i.e. getter "getFoo()" and field "foo"), then 
     * referring to "foo" in template invokes the getter. If set to false, no
     * access to public instance fields of classes is given. Default is false.
     */
    public void setExposeFields(boolean exposeFields) {
        checkModifiable();
        
        if (classIntrospector.getExposeFields() != exposeFields) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setExposeFields(exposeFields);
            replaceClassIntrospector(builder);
        }
    }
    
    /**
     * Controls whether Java 8 default methods that weren't overridden in a class will be recognized as bean property
     * accessors and/or bean actions, and thus will be visible from templates. (We expose bean properties and bean
     * actions, not methods in general.) Before {@link #getIncompatibleImprovements incompatibleImprovements} 2.3.26
     * this defaults to {@code false} for backward compatibility. Starting with {@link #getIncompatibleImprovements
     * incompatibleImprovements} 2.3.26 it defaults to {@code true}.
     * <p>
     * Some explanation: FreeMarker uses {@link java.beans.Introspector} to discover the bean properties and actions of
     * classes, for maximum conformance to the JavaBeans specification. But for some reason (perhaps just a bug in the
     * Oracle/OpenJDK Java 8 implementation) that ignores the Java 8 default methods coming from the interfaces. When
     * this setting is {@code true}, we search for non-overridden default methods ourselves, and add them to the set of
     * discovered bean members.
     * 
     * @since 2.3.26
     */
    public void setTreatDefaultMethodsAsBeanMembers(boolean treatDefaultMethodsAsBeanMembers) {
        checkModifiable();
        
        if (classIntrospector.getTreatDefaultMethodsAsBeanMembers() != treatDefaultMethodsAsBeanMembers) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setTreatDefaultMethodsAsBeanMembers(treatDefaultMethodsAsBeanMembers);
            replaceClassIntrospector(builder);
        }
    }

    /**
     * Sets the {@link ZeroArgumentNonVoidMethodPolicy} for classes that are not Java records;
     * defaults to {@link ZeroArgumentNonVoidMethodPolicy#METHOD_ONLY}.
     *
     * <p>Note that methods in this class are inherited by {@link DefaultObjectWrapper}, which is what you normally use.
     *
     * @since 2.3.33
     */
    public void setNonRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy nonRecordZeroArgumentNonVoidMethodPolicy) {
        checkModifiable();

        if (classIntrospector.getNonRecordZeroArgumentNonVoidMethodPolicy() != nonRecordZeroArgumentNonVoidMethodPolicy) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setNonRecordZeroArgumentNonVoidMethodPolicy(nonRecordZeroArgumentNonVoidMethodPolicy);
            replaceClassIntrospector(builder);
        }
    }

    /**
     * Sets the {@link ZeroArgumentNonVoidMethodPolicy} for classes that are Java records; if the
     * {@code BeansWrapper#BeansWrapper(Version) incompatibleImprovements} of the object wrapper is at least 2.3.33,
     * then this defaults to {@link ZeroArgumentNonVoidMethodPolicy#BOTH_PROPERTY_AND_METHOD}, otherwise this defaults
     * to {@link ZeroArgumentNonVoidMethodPolicy#METHOD_ONLY}.
     *
     * <p>Note that methods in this class are inherited by {@link DefaultObjectWrapper}, which is what you normally use.
     *
     * @since 2.3.33
     */
    public void setRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy recordZeroArgumentNonVoidMethodPolicy) {
        checkModifiable();

        if (classIntrospector.getRecordZeroArgumentNonVoidMethodPolicy() != recordZeroArgumentNonVoidMethodPolicy) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setRecordZeroArgumentNonVoidMethodPolicy(recordZeroArgumentNonVoidMethodPolicy);
            replaceClassIntrospector(builder);
        }
    }

    /**
     * Returns whether exposure of public instance fields of classes is 
     * enabled. See {@link #setExposeFields(boolean)} for details.
     * @return true if public instance fields are exposed, false otherwise.
     * 
     * @since 2.3.26
     */
    public boolean isExposeFields() {
        return classIntrospector.getExposeFields();
    }
    
    /**
     * See {@link #setTreatDefaultMethodsAsBeanMembers(boolean)}.
     */
    public boolean getTreatDefaultMethodsAsBeanMembers() {
        return classIntrospector.getTreatDefaultMethodsAsBeanMembers();
    }

    /**
     * See {@link #setNonRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy)}.
     *
     * @since 2.3.33
     */
    public ZeroArgumentNonVoidMethodPolicy getNonRecordZeroArgumentNonVoidMethodPolicy() {
        return classIntrospector.getNonRecordZeroArgumentNonVoidMethodPolicy();
    }

    /**
     * See {@link #setRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy)}.
     *
     * @since 2.3.33
     */
    public ZeroArgumentNonVoidMethodPolicy getRecordZeroArgumentNonVoidMethodPolicy() {
        return classIntrospector.getRecordZeroArgumentNonVoidMethodPolicy();
    }

    public MethodAppearanceFineTuner getMethodAppearanceFineTuner() {
        return classIntrospector.getMethodAppearanceFineTuner();
    }

    /**
     * Used to tweak certain aspects of how methods appear in the data-model;
     * see {@link MethodAppearanceFineTuner} for more.
     */
    public void setMethodAppearanceFineTuner(MethodAppearanceFineTuner methodAppearanceFineTuner) {
        checkModifiable();
        
        if (classIntrospector.getMethodAppearanceFineTuner() != methodAppearanceFineTuner) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setMethodAppearanceFineTuner(methodAppearanceFineTuner);
            replaceClassIntrospector(builder);
        }
    }

    /**
     * @since 2.3.30
     */
    public MemberAccessPolicy getMemberAccessPolicy() {
        return classIntrospector.getMemberAccessPolicy();
    }

    /**
     * Sets the {@link MemberAccessPolicy}; default is {@link DefaultMemberAccessPolicy#getInstance(Version)}, which
     * is not appropriate if template editors aren't trusted.
     *
     * @since 2.3.30
     */
    public void setMemberAccessPolicy(MemberAccessPolicy memberAccessPolicy) {
        checkModifiable();

        if (classIntrospector.getMemberAccessPolicy() != memberAccessPolicy) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setMemberAccessPolicy(memberAccessPolicy);
            replaceClassIntrospector(builder);
        }
    }

    MethodSorter getMethodSorter() {
        return classIntrospector.getMethodSorter();
    }

    void setMethodSorter(MethodSorter methodSorter) {
        checkModifiable();
        
        if (classIntrospector.getMethodSorter() != methodSorter) {
            ClassIntrospectorBuilder builder = classIntrospector.createBuilder();
            builder.setMethodSorter(methodSorter);
            replaceClassIntrospector(builder);
        }
    }
    
    /**
     * Tells if this instance acts like if its class introspection cache is sharable with other {@link BeansWrapper}-s.
     * A restricted cache denies certain too "antisocial" operations, like {@link #clearClassIntrospectionCache()}.
     * The value depends on how the instance
     * was created; with a public constructor (then this is {@code false}), or with {@link BeansWrapperBuilder}
     * (then it's {@code true}). Note that in the last case it's possible that the introspection cache
     * will not be actually shared because there's no one to share with, but this will {@code true} even then. 
     * 
     * @since 2.3.21
     */
    public boolean isClassIntrospectionCacheRestricted() {
        return classIntrospector.getHasSharedInstanceRestrictions();
    }
    
    /** 
     * Replaces the value of {@link #classIntrospector}, but first it unregisters
     * the model factories in the old {@link #classIntrospector}.
     */
    private void replaceClassIntrospector(ClassIntrospectorBuilder builder) {
        checkModifiable();
        
        final ClassIntrospector newCI = new ClassIntrospector(builder, sharedIntrospectionLock, false, false);
        final ClassIntrospector oldCI;
        
        // In principle this need not be synchronized, but as apps might publish the configuration improperly, or
        // even modify the wrapper after publishing. This doesn't give 100% protection from those violations,
        // as classIntrospector reading aren't everywhere synchronized for performance reasons. It still decreases the
        // chance of accidents, because some ops on classIntrospector are synchronized, and because it will at least
        // push the new value into the common shared memory.
        synchronized (sharedIntrospectionLock) {
            oldCI = classIntrospector;
            if (oldCI != null) {
                // Note that after unregistering the model factory might still gets some callback from the old
                // classIntrospector
                if (staticModels != null) {
                    oldCI.unregisterModelFactory(staticModels);
                    staticModels.clearCache();
                }
                if (enumModels != null) {
                    oldCI.unregisterModelFactory(enumModels);
                    enumModels.clearCache();
                }
                if (modelCache != null) {
                    oldCI.unregisterModelFactory(modelCache);
                    modelCache.clearCache();
                }
                if (trueModel != null) {
                    trueModel.clearMemberCache();
                }
                if (falseModel != null) {
                    falseModel.clearMemberCache();
                }
            }
            
            classIntrospector = newCI;
            
            registerModelFactories();
        }
    }

    private void registerModelFactories() {
        if (staticModels != null) {
            classIntrospector.registerModelFactory(staticModels);
        }
        if (enumModels != null) {
            classIntrospector.registerModelFactory(enumModels);
        }
        if (modelCache != null) {
            classIntrospector.registerModelFactory(modelCache);
        }
    }

    /**
     * Sets whether methods shadow items in beans. When true (this is the
     * default value), <code>${object.name}</code> will first try to locate
     * a bean method or property with the specified name on the object, and
     * only if it doesn't find it will it try to call
     * <code>object.get(name)</code>, the so-called "generic get method" that
     * is usually used to access items of a container (i.e. elements of a map).
     * When set to false, the lookup order is reversed and generic get method
     * is called first, and only if it returns null is method lookup attempted.
     */
    public void setMethodsShadowItems(boolean methodsShadowItems) {
        // This sync is here as this method was originally synchronized, but was never truly thread-safe, so I don't
        // want to advertise it in the javadoc, nor I wanted to break any apps that work because of this accidentally.
        synchronized (this) {
            checkModifiable();
            this.methodsShadowItems = methodsShadowItems;
        }
    }
    
    boolean isMethodsShadowItems() {
        return methodsShadowItems;
    }
    
    /**
     * Sets the default date type to use for date models that result from
     * a plain {@code java.util.Date} instead of {@code java.sql.Date} or
     * {@code java.sql.Time} or {@code java.sql.Timestamp}. Default value is 
     * {@link TemplateDateModel#UNKNOWN}.
     * @param defaultDateType the new default date type.
     */
    public void setDefaultDateType(int defaultDateType) {
        // This sync is here as this method was originally synchronized, but was never truly thread-safe, so I don't
        // want to advertise it in the javadoc, nor I wanted to break any apps that work because of this accidentally.
        synchronized (this) {
            checkModifiable();
            
            this.defaultDateType = defaultDateType;
        }
    }

    /**
     * Returns the default date type. See {@link #setDefaultDateType(int)} for
     * details.
     * @return the default date type
     */
    public int getDefaultDateType() {
        return defaultDateType;
    }
    
    /**
     * Sets whether this wrapper caches the {@link TemplateModel}-s created for the Java objects that has wrapped with
     * this object wrapper. Default is {@code false}.
     * When set to {@code true}, calling {@link #wrap(Object)} multiple times for
     * the same object will likely return the same model (although there is
     * no guarantee as the cache items can be cleared any time).
     */
    public void setUseCache(boolean useCache) {
        checkModifiable();
        modelCache.setUseCache(useCache);
    }

    /**
     * @since 2.3.21
     */
    public boolean getUseCache() {
        return modelCache.getUseCache();
    }
    
    /**
     * Sets the null model. This model is returned from the {@link #wrap(Object)} method whenever the wrapped object is
     * {@code null}. It defaults to {@code null}, which is dealt with quite strictly on engine level, however you can
     * substitute an arbitrary (perhaps more lenient) model, like an empty string. For proper working, the
     * {@code nullModel} should be an {@link AdapterTemplateModel} that returns {@code null} for
     * {@link AdapterTemplateModel#getAdaptedObject(Class)}.
     * 
     * @deprecated Changing the {@code null} model can cause a lot of confusion; don't do it.
     */
    @Deprecated
    public void setNullModel(TemplateModel nullModel) {
        checkModifiable();
        this.nullModel = nullModel;
    }
    
    /**
     * Returns the version given with {@link #BeansWrapper(Version)}, normalized to the lowest version where a change
     * has occurred. Thus, this is not necessarily the same version than that was given to the constructor.
     *
     * @since 2.3.21
     */
    public Version getIncompatibleImprovements() {
        return incompatibleImprovements;
    }
    
    boolean is2321Bugfixed() {
        return is2321Bugfixed(getIncompatibleImprovements());
    }

    static boolean is2321Bugfixed(Version version) {
        return version.intValue() >= _VersionInts.V_2_3_21;
    }

    boolean is2324Bugfixed() {
        return is2324Bugfixed(getIncompatibleImprovements());
    }

    static boolean is2324Bugfixed(Version version) {
        return version.intValue() >= _VersionInts.V_2_3_24;
    }
    
    /** 
     * Returns the lowest version number that is equivalent with the parameter version.
     * @since 2.3.21
     */
    protected static Version normalizeIncompatibleImprovementsVersion(Version incompatibleImprovements) {
        _TemplateAPI.checkVersionNotNullAndSupported(incompatibleImprovements);
        return incompatibleImprovements.intValue() >= _VersionInts.V_2_3_33 ? Configuration.VERSION_2_3_33
                : incompatibleImprovements.intValue() >= _VersionInts.V_2_3_27 ? Configuration.VERSION_2_3_27
                : incompatibleImprovements.intValue() == _VersionInts.V_2_3_26 ? Configuration.VERSION_2_3_26
                : is2324Bugfixed(incompatibleImprovements) ? Configuration.VERSION_2_3_24
                : is2321Bugfixed(incompatibleImprovements) ? Configuration.VERSION_2_3_21
                : Configuration.VERSION_2_3_0;
    }
    
    /**
     * Returns the default instance of the wrapper. This instance is used
     * when you construct various bean models without explicitly specifying
     * a wrapper. It is also returned by 
     * {@link freemarker.template.ObjectWrapper#BEANS_WRAPPER}
     * and this is the sole instance that is used by the JSP adapter.
     * You can modify the properties of the default instance (caching,
     * exposure level, null model) to affect its operation. By default, the
     * default instance is not caching, uses the <code>EXPOSE_SAFE</code>
     * exposure level, and uses null reference as the null model.
     * 
     * @deprecated Use {@link BeansWrapperBuilder} instead. The instance returned here is not read-only, so it's
     *     dangerous to use.
     */
    @Deprecated
    public static final BeansWrapper getDefaultInstance() {
        return BeansWrapperSingletonHolder.INSTANCE;
    }

    /**
     * Wraps the object with a template model that is most specific for the object's
     * class. Specifically:
     * <ul>
     * <li>if the object is null, returns the {@link #setNullModel(TemplateModel) null model},</li>
     * <li>if the object is a Number returns a {@link NumberModel} for it,</li>
     * <li>if the object is a Date returns a {@link DateModel} for it,</li>
     * <li>if the object is a Boolean returns 
     * {@link freemarker.template.TemplateBooleanModel#TRUE} or 
     * {@link freemarker.template.TemplateBooleanModel#FALSE}</li>
     * <li>if the object is already a TemplateModel, returns it unchanged,</li>
     * <li>if the object is an array, returns a {@link ArrayModel} for it
     * <li>if the object is a Map, returns a {@link MapModel} for it
     * <li>if the object is a Collection, returns a {@link CollectionModel} for it
     * <li>if the object is an Iterator, returns a {@link IteratorModel} for it
     * <li>if the object is an Enumeration, returns a {@link EnumerationModel} for it
     * <li>if the object is a String, returns a {@link StringModel} for it
     * <li>otherwise, returns a {@link GenericObjectModel} for it.
     * </ul>
     */
    @Override
    public TemplateModel wrap(Object object) throws TemplateModelException {
        if (object == null) return nullModel;
        return modelCache.getInstance(object);
    }
    
    /**
     * Wraps a Java method so that it can be called from templates, without wrapping its parent ("this") object. The
     * result is almost the same as that you would get by wrapping the parent object then getting the method from the
     * resulting {@link TemplateHashModel} by name. Except, if the wrapped method is overloaded, with this method you
     * explicitly select an overload, while otherwise you would get a {@link TemplateMethodModelEx} that selects an
     * overload each time it's called based on the argument values.
     * 
     * @param object The object whose method will be called, or {@code null} if {@code method} is a static method.
     *          This object will be used "as is", like without unwrapping it if it's a {@link TemplateModelAdapter}.
     * @param method The method to call, which must be an (inherited) member of the class of {@code object}, as
     *          described by {@link Method#invoke(Object, Object...)}
     * 
     * @since 2.3.22
     */
    public TemplateMethodModelEx wrap(Object object, Method method) {
        return new SimpleMethodModel(object, method, method.getParameterTypes(), this);
    }
    
    /**
     * @since 2.3.22
     */
    @Override
    public TemplateHashModel wrapAsAPI(Object obj) throws TemplateModelException {
        return new APIModel(obj, this);
    }

    /**
     * @deprecated override {@link #getModelFactory(Class)} instead. Using this
     * method will now bypass wrapper caching (if it's enabled) and always 
     * result in creation of a new wrapper. This method will be removed in 2.4
     * @param object The object to wrap
     * @param factory The factory that wraps the object
     */
    @Deprecated
    protected TemplateModel getInstance(Object object, ModelFactory factory) {
        return factory.create(object, this);
    }

    private final ModelFactory BOOLEAN_FACTORY = new ModelFactory() {
        @Override
        public TemplateModel create(Object object, ObjectWrapper wrapper) {
            return ((Boolean) object).booleanValue() ? trueModel : falseModel; 
        }
    };

    private static final ModelFactory ITERATOR_FACTORY = new ModelFactory() {
        @Override
        public TemplateModel create(Object object, ObjectWrapper wrapper) {
            return new IteratorModel((Iterator<?>) object, (BeansWrapper) wrapper); 
        }
    };

    private static final ModelFactory ENUMERATION_FACTORY = new ModelFactory() {
        @Override
        public TemplateModel create(Object object, ObjectWrapper wrapper) {
            return new EnumerationModel((Enumeration<?>) object, (BeansWrapper) wrapper); 
        }
    };

    protected ModelFactory getModelFactory(Class<?> clazz) {
        if (Map.class.isAssignableFrom(clazz)) {
            return simpleMapWrapper ? SimpleMapModel.FACTORY : MapModel.FACTORY;
        }
        if (Collection.class.isAssignableFrom(clazz)) {
            return CollectionModel.FACTORY;
        }
        if (Number.class.isAssignableFrom(clazz)) {
            return NumberModel.FACTORY;
        }
        if (Date.class.isAssignableFrom(clazz)) {
            return DateModel.FACTORY;
        }
        if (Boolean.class == clazz) { // Boolean is final 
            return BOOLEAN_FACTORY;
        }
        if (ResourceBundle.class.isAssignableFrom(clazz)) {
            return ResourceBundleModel.FACTORY;
        }
        if (Iterator.class.isAssignableFrom(clazz)) {
            return ITERATOR_FACTORY;
        }
        if (Enumeration.class.isAssignableFrom(clazz)) {
            return ENUMERATION_FACTORY;
        }
        if (clazz.isArray()) {
            return ArrayModel.FACTORY;
        }
        return GenericObjectModel.FACTORY;
    }

    /**
     * Attempts to unwrap a model into underlying object. Generally, this
     * method is the inverse of the {@link #wrap(Object)} method. In addition
     * it will unwrap arbitrary {@link TemplateNumberModel} instances into
     * a number, arbitrary {@link TemplateDateModel} instances into a date,
     * {@link TemplateScalarModel} instances into a String, arbitrary 
     * {@link TemplateBooleanModel} instances into a Boolean, arbitrary 
     * {@link TemplateHashModel} instances into a Map, arbitrary 
     * {@link TemplateSequenceModel} into a List, and arbitrary 
     * {@link TemplateCollectionModel} into a Set. All other objects are 
     * returned unchanged.
     * @throws TemplateModelException if an attempted unwrapping fails.
     */
    @Override
    public Object unwrap(TemplateModel model) throws TemplateModelException {
        return unwrap(model, Object.class);
    }

    /**
     * Attempts to unwrap a model into an object of the desired class. 
     * Generally, this method is the inverse of the {@link #wrap(Object)} 
     * method. It recognizes a wide range of target classes - all Java built-in
     * primitives, primitive wrappers, numbers, dates, sets, lists, maps, and
     * native arrays.
     * @param model the model to unwrap
     * @param targetClass the class of the unwrapped result; {@code Object.class} if we don't know what the expected type is.
     * @return the unwrapped result of the desired class
     * @throws TemplateModelException if an attempted unwrapping fails.
     * 
     * @see #tryUnwrapTo(TemplateModel, Class)
     */
    public Object unwrap(TemplateModel model, Class<?> targetClass) 
    throws TemplateModelException {
        final Object obj = tryUnwrapTo(model, targetClass);
        if (obj == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) {
          throw new TemplateModelException("Can not unwrap model of type " + 
              model.getClass().getName() + " to type " + targetClass.getName());
        }
        return obj;
    }

    /**
     * @since 2.3.22
     */
    @Override
    public Object tryUnwrapTo(TemplateModel model, Class<?> targetClass) throws TemplateModelException {
        return tryUnwrapTo(model, targetClass, 0);
    }
    
    /**
     * @param typeFlags
     *            Used when unwrapping for overloaded methods and so the {@code targetClass} is possibly too generic.
     *            Must be 0 when unwrapping parameter values for non-overloaded methods, also if
     *            {@link #is2321Bugfixed()} is {@code false}.
     * @return {@link ObjectWrapperAndUnwrapper#CANT_UNWRAP_TO_TARGET_CLASS} or the unwrapped object.
     */
    Object tryUnwrapTo(TemplateModel model, Class<?> targetClass, int typeFlags) 
    throws TemplateModelException {
        Object res = tryUnwrapTo(model, targetClass, typeFlags, null);
        if ((typeFlags & TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT) != 0
                && res instanceof Number) {
            return OverloadedNumberUtil.addFallbackType((Number) res, typeFlags);
        } else {
            return res;
        }
    }

    /**
     * See {@link #tryUnwrapTo(TemplateModel, Class, int)}.
     */
    private Object tryUnwrapTo(final TemplateModel model, Class<?> targetClass, final int typeFlags,
            final Map<Object, Object> recursionStops) 
    throws TemplateModelException {
        if (model == null || model == nullModel) {
            return null;
        }
        
        final boolean is2321Bugfixed = is2321Bugfixed();
        
        if (is2321Bugfixed && targetClass.isPrimitive()) {
            targetClass = ClassUtil.primitiveClassToBoxingClass(targetClass);            
        }
        
        // This is for transparent interop with other wrappers (and ourselves)
        // Passing the targetClass allows i.e. a Jython-aware method that declares a
        // PyObject as its argument to receive a PyObject from a JythonModel
        // passed as an argument to TemplateMethodModelEx etc.
        if (model instanceof AdapterTemplateModel) {
            Object wrapped = ((AdapterTemplateModel) model).getAdaptedObject(
                    targetClass);
            if (targetClass == Object.class || targetClass.isInstance(wrapped)) {
                return wrapped;
            }
            
            // Attempt numeric conversion: 
            if (targetClass != Object.class && (wrapped instanceof Number && ClassUtil.isNumerical(targetClass))) {
                Number number = forceUnwrappedNumberToType((Number) wrapped, targetClass, is2321Bugfixed);
                if (number != null) return number;
            }
        }
        
        if (model instanceof WrapperTemplateModel) {
            Object wrapped = ((WrapperTemplateModel) model).getWrappedObject();
            if (targetClass == Object.class || targetClass.isInstance(wrapped)) {
                return wrapped;
            }
            
            // Attempt numeric conversion: 
            if (targetClass != Object.class && (wrapped instanceof Number && ClassUtil.isNumerical(targetClass))) {
                Number number = forceUnwrappedNumberToType((Number) wrapped, targetClass, is2321Bugfixed);
                if (number != null) {
                    return number;
                }
            }
        }
        
        // Translation of generic template models to POJOs. First give priority
        // to various model interfaces based on the targetClass. This helps us
        // select the appropriate interface in multi-interface models when we
        // know what is expected as the return type.
        if (targetClass != Object.class) {

            // [2.4][IcI]: Should also check for CharSequence at the end
            if (String.class == targetClass) {
                if (model instanceof TemplateScalarModel) {
                    return ((TemplateScalarModel) model).getAsString();
                }
                // String is final, so no other conversion will work
                return ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
            }
    
            // Primitive numeric types & Number.class and its subclasses
            if (ClassUtil.isNumerical(targetClass)) {
                if (model instanceof TemplateNumberModel) {
                    Number number = forceUnwrappedNumberToType(
                            ((TemplateNumberModel) model).getAsNumber(), targetClass, is2321Bugfixed);
                    if (number != null) {
                        return number;
                    }
                }
            }
            
            if (boolean.class == targetClass || Boolean.class == targetClass) {
                if (model instanceof TemplateBooleanModel) {
                    return Boolean.valueOf(((TemplateBooleanModel) model).getAsBoolean());
                }
                // Boolean is final, no other conversion will work
                return ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
            }
    
            if (Map.class == targetClass) {
                if (model instanceof TemplateHashModel) {
                    return new HashAdapter((TemplateHashModel) model, this);
                }
            }
            
            if (List.class == targetClass) {
                if (model instanceof TemplateSequenceModel) {
                    return new SequenceAdapter((TemplateSequenceModel) model, this);
                }
            }
            
            if (Set.class == targetClass) {
                if (model instanceof TemplateCollectionModel) {
                    return new SetAdapter((TemplateCollectionModel) model, this);
                }
            }
            
            if (Collection.class == targetClass || Iterable.class == targetClass) {
                if (model instanceof TemplateCollectionModel) {
                    return new CollectionAdapter((TemplateCollectionModel) model, 
                            this);
                }
                if (model instanceof TemplateSequenceModel) {
                    return new SequenceAdapter((TemplateSequenceModel) model, this);
                }
            }
            
            // TemplateSequenceModels can be converted to arrays
            if (targetClass.isArray()) {
                if (model instanceof TemplateSequenceModel) {
                    return unwrapSequenceToArray((TemplateSequenceModel) model, targetClass, true, recursionStops);
                }
                // array classes are final, no other conversion will work
                return ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
            }
            
            // Allow one-char strings to be coerced to characters
            if (char.class == targetClass || targetClass == Character.class) {
                if (model instanceof TemplateScalarModel) {
                    String s = ((TemplateScalarModel) model).getAsString();
                    if (s.length() == 1) {
                        return Character.valueOf(s.charAt(0));
                    }
                }
                // Character is final, no other conversion will work
                return ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
            }
    
            if (Date.class.isAssignableFrom(targetClass) && model instanceof TemplateDateModel) {
                Date date = ((TemplateDateModel) model).getAsDate();
                if (targetClass.isInstance(date)) {
                    return date;
                }
            }
        }  //  End: if (targetClass != Object.class)
        
        // Since the targetClass was of no help initially, now we use
        // a quite arbitrary order in which we walk through the TemplateModel subinterfaces, and unwrapp them to
        // their "natural" Java correspondent. We still try exclude unwrappings that won't fit the target parameter
        // type(s). This is mostly important because of multi-typed FTL values that could be unwrapped on multiple ways.
        int itf = typeFlags; // Iteration's Type Flags. Should be always 0 for non-overloaded and when !is2321Bugfixed.
        // If itf != 0, we possibly execute the following loop body at twice: once with utilizing itf, and if it has not
        // returned, once more with itf == 0. Otherwise we execute this once with itf == 0.
        do {
            if ((itf == 0 || (itf & TypeFlags.ACCEPTS_NUMBER) != 0)
                    && model instanceof TemplateNumberModel) {
                Number number = ((TemplateNumberModel) model).getAsNumber();
                if (itf != 0 || targetClass.isInstance(number)) {
                    return number;
                }
            }
            if ((itf == 0 || (itf & TypeFlags.ACCEPTS_DATE) != 0)
                    && model instanceof TemplateDateModel) {
                Date date = ((TemplateDateModel) model).getAsDate();
                if (itf != 0 || targetClass.isInstance(date)) {
                    return date;
                }
            }
            if ((itf == 0 || (itf & (TypeFlags.ACCEPTS_STRING | TypeFlags.CHARACTER)) != 0)
                    && model instanceof TemplateScalarModel
                    && (itf != 0 || targetClass.isAssignableFrom(String.class))) {
                String strVal = ((TemplateScalarModel) model).getAsString();
                if (itf == 0 || (itf & TypeFlags.CHARACTER) == 0) {
                    return strVal;
                } else { // TypeFlags.CHAR == 1
                    if (strVal.length() == 1) {
                        if ((itf & TypeFlags.ACCEPTS_STRING) != 0) {
                            return new CharacterOrString(strVal);
                        } else {
                            return Character.valueOf(strVal.charAt(0));
                        }
                    } else if ((itf & TypeFlags.ACCEPTS_STRING) != 0) {
                        return strVal; 
                    }
                    // It had to be unwrapped to Character, but the string length wasn't 1 => Fall through
                }
            }
            // Should be earlier than TemplateScalarModel, but we keep it here until FM 2.4 or such
            if ((itf == 0 || (itf & TypeFlags.ACCEPTS_BOOLEAN) != 0)
                    && model instanceof TemplateBooleanModel
                    && (itf != 0 || targetClass.isAssignableFrom(Boolean.class))) {
                return Boolean.valueOf(((TemplateBooleanModel) model).getAsBoolean());
            }
            if ((itf == 0 || (itf & TypeFlags.ACCEPTS_MAP) != 0)
                    && model instanceof TemplateHashModel
                    && (itf != 0 || targetClass.isAssignableFrom(HashAdapter.class))) {
                return new HashAdapter((TemplateHashModel) model, this);
            }
            if ((itf == 0 || (itf & TypeFlags.ACCEPTS_LIST) != 0)
                    && model instanceof TemplateSequenceModel 
                    && (itf != 0 || targetClass.isAssignableFrom(SequenceAdapter.class))) {
                return new SequenceAdapter((TemplateSequenceModel) model, this);
            }
            if ((itf == 0 || (itf & TypeFlags.ACCEPTS_SET) != 0)
                    && model instanceof TemplateCollectionModel
                    && (itf != 0 || targetClass.isAssignableFrom(SetAdapter.class))) {
                return new SetAdapter((TemplateCollectionModel) model, this);
            }
            
            // In 2.3.21 bugfixed mode only, List-s are convertible to arrays on invocation time. Only overloaded
            // methods need this. As itf will be 0 in non-bugfixed mode and for non-overloaded method calls, it's
            // enough to check if the TypeFlags.ACCEPTS_ARRAY bit is 1:
            if ((itf & TypeFlags.ACCEPTS_ARRAY) != 0
                    && model instanceof TemplateSequenceModel) {
                return new SequenceAdapter((TemplateSequenceModel) model, this);
            }
            
            if (itf == 0) {
                break;
            }
            itf = 0; // start 2nd iteration
        } while (true);

        // Last ditch effort - is maybe the model itself is an instance of the required type?
        // Note that this will be always true for Object.class targetClass. 
        if (targetClass.isInstance(model)) {
            return model;
        }
        
        return ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
    }

    /**
     * @param tryOnly
     *            If {@code true}, if the conversion of an item to the component type isn't possible, the method returns
     *            {@link ObjectWrapperAndUnwrapper#CANT_UNWRAP_TO_TARGET_CLASS} instead of throwing a
     *            {@link TemplateModelException}.
     */
    Object unwrapSequenceToArray(
            TemplateSequenceModel seq, Class<?> arrayClass, boolean tryOnly, Map<Object, Object> recursionStops)
            throws TemplateModelException {
        if (recursionStops != null) {
            Object retval = recursionStops.get(seq);
            if (retval != null) {
                return retval;
            }
        } else {
            recursionStops = new IdentityHashMap<>();
        }
        Class<?> componentType = arrayClass.getComponentType();
        final int size = seq.size();
        Object array = Array.newInstance(componentType, size);
        recursionStops.put(seq, array);
        try {
            for (int i = 0; i < size; i++) {
                final TemplateModel seqItem = seq.get(i);
                Object val = tryUnwrapTo(seqItem, componentType, 0, recursionStops);
                if (val == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) {
                    if (tryOnly) {
                        return ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
                    } else {
                        throw new _TemplateModelException(
                                "Failed to convert ",  new _DelayedFTLTypeDescription(seq),
                                " object to ", new _DelayedShortClassName(array.getClass()),
                                ": Problematic sequence item at index ", Integer.valueOf(i) ," with value type: ",
                                new _DelayedFTLTypeDescription(seqItem));
                    }
                    
                }
                Array.set(array, i, val);
            }
        } finally {
            recursionStops.remove(seq);
        }
        return array;
    }
    
    Object listToArray(List<?> list, Class<?> arrayClass, Map<Object, Object> recursionStops)
            throws TemplateModelException {
        if (list instanceof SequenceAdapter) {
            return unwrapSequenceToArray(
                    ((SequenceAdapter) list).getTemplateSequenceModel(),
                    arrayClass, false,
                    recursionStops);
        }
        
        if (recursionStops != null) {
            Object retval = recursionStops.get(list);
            if (retval != null) {
                return retval;
            }
        } else {
            recursionStops = new IdentityHashMap<>();
        }
        Class<?> componentType = arrayClass.getComponentType();
        Object array = Array.newInstance(componentType, list.size());
        recursionStops.put(list, array);
        try {
            boolean isComponentTypeExamined = false;
            boolean isComponentTypeNumerical = false;  // will be filled on demand
            boolean isComponentTypeList = false;  // will be filled on demand
            int i = 0;
            for (Iterator<?> it = list.iterator(); it.hasNext(); ) {
                Object listItem = it.next();
                if (listItem != null && !componentType.isInstance(listItem)) {
                    // Type conversion is needed. If we can't do it, we just let it fail at Array.set later.
                    if (!isComponentTypeExamined) {
                        isComponentTypeNumerical = ClassUtil.isNumerical(componentType);
                        isComponentTypeList = List.class.isAssignableFrom(componentType);
                        isComponentTypeExamined = true;
                    }
                    if (isComponentTypeNumerical && listItem instanceof Number) {
                        listItem = forceUnwrappedNumberToType((Number) listItem, componentType, true);
                    } else if (componentType == String.class && listItem instanceof Character) {
                        listItem = String.valueOf(((Character) listItem).charValue());
                    } else if ((componentType == Character.class || componentType == char.class)
                            && listItem instanceof String) {
                        String listItemStr = (String) listItem;
                        if (listItemStr.length() == 1) {
                            listItem = Character.valueOf(listItemStr.charAt(0));
                        }
                    } else if (componentType.isArray()) {
                        if (listItem instanceof List) {
                            listItem = listToArray((List<?>) listItem, componentType, recursionStops);
                        } else if (listItem instanceof TemplateSequenceModel) {
                            listItem = unwrapSequenceToArray((TemplateSequenceModel) listItem, componentType, false, recursionStops);
                        }
                    } else if (isComponentTypeList && listItem.getClass().isArray()) {
                        listItem = arrayToList(listItem);
                    }
                }
                try {
                    Array.set(array, i, listItem);
                } catch (IllegalArgumentException e) {
                    throw new TemplateModelException(
                            "Failed to convert " + ClassUtil.getShortClassNameOfObject(list)
                            + " object to " + ClassUtil.getShortClassNameOfObject(array)
                            + ": Problematic List item at index " + i + " with value type: "
                            + ClassUtil.getShortClassNameOfObject(listItem), e);
                }
                i++;
            }
        } finally {
            recursionStops.remove(list);
        }
        return array;
    }
    
    /**
     * @param array Must be an array (of either a reference or primitive type)
     */
    List<?> arrayToList(Object array) throws TemplateModelException {
        if (array instanceof Object[]) {
            // Array of any non-primitive type.
            // Note that an array of non-primitive type is always instanceof Object[].
            Object[] objArray = (Object[]) array;
            return objArray.length == 0 ? Collections.EMPTY_LIST : new NonPrimitiveArrayBackedReadOnlyList(objArray);
        } else {
            // Array of any primitive type
            return Array.getLength(array) == 0 ? Collections.EMPTY_LIST : new PrimtiveArrayBackedReadOnlyList(array);
        }
    }

    /**
     * Converts a number to the target type aggressively (possibly with overflow or significant loss of precision).
     * @param n Non-{@code null}
     * @return {@code null} if the conversion has failed.
     */
    static Number forceUnwrappedNumberToType(final Number n, final Class<?> targetType, final boolean bugfixed) {
        // We try to order the conditions by decreasing probability.
        if (targetType == n.getClass()) {
            return n;
        } else if (targetType == int.class || targetType == Integer.class) {
            return n instanceof Integer ? (Integer) n : Integer.valueOf(n.intValue());
        } else if (targetType == long.class || targetType == Long.class) {
            return n instanceof Long ? (Long) n : Long.valueOf(n.longValue());
        } else if (targetType == double.class || targetType == Double.class) {
            return n instanceof Double ? (Double) n : Double.valueOf(n.doubleValue());
        } else if (targetType == BigDecimal.class) {
            if (n instanceof BigDecimal) {
                return n;
            } else if (n instanceof BigInteger) {
                return new BigDecimal((BigInteger) n);
            } else if (n instanceof Long) {
                // Because we can't represent long accurately as double
                return BigDecimal.valueOf(n.longValue());
            } else {
                return new BigDecimal(n.doubleValue());
            }
        } else if (targetType == float.class || targetType == Float.class) {
            return n instanceof Float ? (Float) n : Float.valueOf(n.floatValue());
        } else if (targetType == byte.class || targetType == Byte.class) {
            return n instanceof Byte ? (Byte) n : Byte.valueOf(n.byteValue());
        } else if (targetType == short.class || targetType == Short.class) {
            return n instanceof Short ? (Short) n : Short.valueOf(n.shortValue());
        } else if (targetType == BigInteger.class) {
            if (n instanceof BigInteger) {
                return n;
            } else if (bugfixed) {
                if (n instanceof OverloadedNumberUtil.IntegerBigDecimal) {
                    return ((OverloadedNumberUtil.IntegerBigDecimal) n).bigIntegerValue();
                } else if (n instanceof BigDecimal) {
                    return ((BigDecimal) n).toBigInteger(); 
                } else {
                    return BigInteger.valueOf(n.longValue()); 
                }
            } else {
                // This is wrong, because something like "123.4" will cause NumberFormatException instead of flooring.
                return new BigInteger(n.toString());
            }
        } else {
            final Number oriN = n instanceof OverloadedNumberUtil.NumberWithFallbackType
                    ? ((OverloadedNumberUtil.NumberWithFallbackType) n).getSourceNumber() : n; 
            if (targetType.isInstance(oriN)) {
                // Handle nonstandard Number subclasses as well as directly java.lang.Number.
                return oriN;
            } else {
                // Fails
                return null;
            }
        }
    }

    /**
     * Invokes the specified method, wrapping the return value. All method invocations done in templates should go
     * through this (assuming the target object was wrapped with this {@link ObjectWrapper}).
     *
     * <p>This method is protected since 2.3.30; before that it was package private. The intended application of
     * overriding this is monitoring what calls are made from templates. That can be useful to asses what will be needed
     * in a {@link WhitelistMemberAccessPolicy} for example. Note that {@link Object#toString} calls caused by type
     * conversion (like when you have <code>${myObject}</code>) will not go through here, as they aren't called by the
     * template directly (and aren't called via reflection). On the other hand, <code>${myObject[key]}</code>,
     * if {@code myObject} is not a {@link Map}, will go through here as a {@code get(String|Object)} method call, if
     * there's a such method.
     *
     * <p>If the return value is null, and the return type of the invoked method is void,
     * {@link TemplateModel#NOTHING} is returned.
     *
     * @param object the object to invoke the method on ({@code null} may be null for static methods)
     * @param method the method to invoke 
     * @param args the arguments to the method
     * @return the wrapped return value of the method.
     * @throws InvocationTargetException if the invoked method threw an exception
     * @throws IllegalAccessException if the method can't be invoked due to an
     * access restriction. 
     * @throws TemplateModelException if the return value couldn't be wrapped
     * (this can happen if the wrapper has an outer identity or is subclassed,
     * and the outer identity or the subclass throws an exception. Plain
     * BeansWrapper never throws TemplateModelException).
     *
     * @see #readField(Object, Field)
     *
     * @since 2.3.30
     */
    protected TemplateModel invokeMethod(Object object, Method method, Object[] args)
            throws InvocationTargetException,
        IllegalAccessException,
        TemplateModelException {
        // [2.4]: Java's Method.invoke truncates numbers if the target type has not enough bits to hold the value.
        // There should at least be an option to check this.
        Object retval = method.invoke(object, args);
        return 
            method.getReturnType() == void.class 
            ? TemplateModel.NOTHING
            : getOuterIdentity().wrap(retval); 
    }

    /**
     * Reads the specified field, returns its value as {@link TemplateModel}.  All field reading done in templates
     * should go through this (assuming the target object was wrapped with this {@link ObjectWrapper}).
     *
     * <p>Just like in the case of {@link #invokeMethod(Object, Method, Object[])}, overriding this can be useful if you
     * want to monitor what members are accessed by templates. However, it has the caveat that final field values are
     * possibly cached, so you won't see all reads. Furthermore, at least static models pre-read final fields, so
     * they will be read even if the templates don't read them.
     *
     * @see #invokeMethod(Object, Method, Object[])
     *
     * @since 2.3.30
     */
    protected TemplateModel readField(Object object, Field field)
            throws IllegalAccessException, TemplateModelException {
        return getOuterIdentity().wrap(field.get(object));
    }

   /**
     * Returns a hash model that represents the so-called class static models.
     * Every class static model is itself a hash through which you can call
     * static methods on the specified class. To obtain a static model for a
     * class, get the element of this hash with the fully qualified class name.
     * For example, if you place this hash model inside the root data model
     * under name "statics", you can use i.e. <code>statics["java.lang.
     * System"]. currentTimeMillis()</code> to call the {@link 
     * java.lang.System#currentTimeMillis()} method.
     * @return a hash model whose keys are fully qualified class names, and
     * that returns hash models whose elements are the static models of the
     * classes.
     */
    public TemplateHashModel getStaticModels() {
        return staticModels;
    }

    /**
     * Returns a hash model that represents the so-called class enum models.
     * Every class' enum model is itself a hash through which you can access
     * enum value declared by the specified class, assuming that class is an
     * enumeration. To obtain an enum model for a class, get the element of this
     * hash with the fully qualified class name. For example, if you place this 
     * hash model inside the root data model under name "enums", you can use 
     * i.e. <code>enums["java.math.RoundingMode"].UP</code> to access the 
     * {@link java.math.RoundingMode#UP} value.
     * @return a hash model whose keys are fully qualified class names, and
     * that returns hash models whose elements are the enum models of the
     * classes.
     * @throws UnsupportedOperationException if this method is invoked on a 
     * pre-1.5 JRE, as Java enums aren't supported there.
     */
    public TemplateHashModel getEnumModels() {
        if (enumModels == null) {
            throw new UnsupportedOperationException(
                    "Enums not supported before J2SE 5.");
        }
        return enumModels;
    }
    
    /** For Unit tests only */
    ModelCache getModelCache() {
        return modelCache;
    }

    /**
     * Creates a new instance of the specified class using the method call logic of this object wrapper for calling the
     * constructor. Overloaded constructors and varargs are supported. Only public constructors will be called.
     * 
     * @param clazz The class whose constructor we will call.
     * @param arguments The list of {@link TemplateModel}-s to pass to the constructor after unwrapping them
     * @return The instance created; it's not wrapped into {@link TemplateModel}.
     */
    public Object newInstance(Class<?> clazz, List/*<? extends TemplateModel>*/ arguments)
    throws TemplateModelException {
        try {
            Object ctors = classIntrospector.get(clazz).get(ClassIntrospector.CONSTRUCTORS_KEY);
            if (ctors == null) {
                throw new TemplateModelException("Class " + clazz.getName() + 
                        " has no exposed constructors.");
            }
            Constructor<?> ctor = null;
            Object[] objargs;
            if (ctors instanceof SimpleMethod) {
                SimpleMethod sm = (SimpleMethod) ctors;
                ctor = (Constructor<?>) sm.getMember();
                objargs = sm.unwrapArguments(arguments, this);
                try {
                    return ctor.newInstance(objargs);
                } catch (Exception e) {
                    if (e instanceof TemplateModelException) throw (TemplateModelException) e;
                    throw _MethodUtil.newInvocationTemplateModelException(null, ctor, e);
                }
            } else if (ctors instanceof OverloadedMethods) {
                final MemberAndArguments mma = ((OverloadedMethods) ctors).getMemberAndArguments(arguments, this);
                try {
                    return mma.invokeConstructor(this);
                } catch (Exception e) {
                    if (e instanceof TemplateModelException) throw (TemplateModelException) e;
                    
                    throw _MethodUtil.newInvocationTemplateModelException(null, mma.getCallableMemberDescriptor(), e);
                }
            } else {
                // Cannot happen
                throw new BugException();
            }
        } catch (TemplateModelException e) {
            throw e;
        } catch (Exception e) {
            throw new TemplateModelException(
                    "Error while creating new instance of class " + clazz.getName() + "; see cause exception", e);
        }
    }

    /**
     * Removes the introspection data for a class from the cache.
     * Use this if you know that a class is not used anymore in templates.
     * If the class will be still used, the cache entry will be silently
     * re-created, so this isn't a dangerous operation.
     * 
     * @since 2.3.20
     */
    public void removeFromClassIntrospectionCache(Class<?> clazz) {
        classIntrospector.remove(clazz);
    }
    
    /**
     * <p>Removes all class introspection data from the cache.
     * 
     * <p>Use this if you want to free up memory on the expense of recreating
     * the cache entries for the classes that will be used later in templates.
     * 
     * @throws IllegalStateException if {@link #isClassIntrospectionCacheRestricted()} is {@code true}.
     * 
     * @since 2.3.20
     *
     * @deprecated There's a typo in this method name, so use {@link #clearClassIntrospectionCache()} instead.
     */
    @Deprecated
    public void clearClassIntrospecitonCache() {
        classIntrospector.clearCache();
    }

    /**
     * Removes all class introspection data from the cache.
     *
     * <p>Use this if you want to free up memory on the expense of recreating
     * the cache entries for the classes that will be used later in templates.
     *
     * @throws IllegalStateException if {@link #isClassIntrospectionCacheRestricted()} is {@code true}.
     *
     * @since 2.3.29 (in earlier versions use {@link #clearClassIntrospecitonCache()})
     */
    public void clearClassIntrospectionCache() {
        classIntrospector.clearCache();
    }

    ClassIntrospector getClassIntrospector() {
        return classIntrospector;
    }
    
    /**
     * @deprecated Use {@link #setMethodAppearanceFineTuner(MethodAppearanceFineTuner)};
     *     no need to extend this class anymore.
     *     Soon this method will be final, so trying to override it will break your app.
     *     Note that if the {@code methodAppearanceFineTuner} property is set to non-{@code null}, this method is not
     *     called anymore.
     */
    @Deprecated
    protected void finetuneMethodAppearance(
            Class<?> clazz, Method m, MethodAppearanceDecision decision) {
        // left everything on its default; do nothing
    }
    
    /**
     * Converts any {@link BigDecimal}s in the passed array to the type of
     * the corresponding formal argument of the method.
     */
    // Unused?
    public static void coerceBigDecimals(AccessibleObject callable, Object[] args) {
        Class<?>[] formalTypes = null;
        for (int i = 0; i < args.length; ++i) {
            Object arg = args[i];
            if (arg instanceof BigDecimal) {
                if (formalTypes == null) {
                    if (callable instanceof Method) {
                        formalTypes = ((Method) callable).getParameterTypes();
                    } else if (callable instanceof Constructor) {
                        formalTypes = ((Constructor<?>) callable).getParameterTypes();
                    } else {
                        throw new IllegalArgumentException("Expected method or "
                                + " constructor; callable is " + 
                                callable.getClass().getName());
                    }
                }
                args[i] = coerceBigDecimal((BigDecimal) arg, formalTypes[i]);
            }
        }
    }
    
    /**
     * Converts any {@link BigDecimal}-s in the passed array to the type of
     * the corresponding formal argument of the method via {@link #coerceBigDecimal(BigDecimal, Class)}.
     */
    public static void coerceBigDecimals(Class<?>[] formalTypes, Object[] args) {
        int typeLen = formalTypes.length;
        int argsLen = args.length;
        int min = Math.min(typeLen, argsLen);
        for (int i = 0; i < min; ++i) {
            Object arg = args[i];
            if (arg instanceof BigDecimal) {
                args[i] = coerceBigDecimal((BigDecimal) arg, formalTypes[i]);
            }
        }
        if (argsLen > typeLen) {
            Class<?> varArgType = formalTypes[typeLen - 1];
            for (int i = typeLen; i < argsLen; ++i) {
                Object arg = args[i];
                if (arg instanceof BigDecimal) {
                    args[i] = coerceBigDecimal((BigDecimal) arg, varArgType);
                }
            }
        }
    }

    /**
     * Converts {@link BigDecimal} to the class given in the {@code formalType} argument if that's a known numerical
     * type, returns the {@link BigDecimal} as is otherwise. Overflow and precision loss are possible, similarly as
     * with casting in Java.
     */
    public static Object coerceBigDecimal(BigDecimal bd, Class<?> formalType) {
        // int is expected in most situations, so we check it first
        if (formalType == int.class || formalType == Integer.class) {
            return Integer.valueOf(bd.intValue());
        } else if (formalType == double.class || formalType == Double.class) {
            return Double.valueOf(bd.doubleValue());
        } else if (formalType == long.class || formalType == Long.class) {
            return Long.valueOf(bd.longValue());
        } else if (formalType == float.class || formalType == Float.class) {
            return Float.valueOf(bd.floatValue());
        } else if (formalType == short.class || formalType == Short.class) {
            return Short.valueOf(bd.shortValue());
        } else if (formalType == byte.class || formalType == Byte.class) {
            return Byte.valueOf(bd.byteValue());
        } else if (java.math.BigInteger.class.isAssignableFrom(formalType)) {
            return bd.toBigInteger();
        } else {
            return bd;
        }
    }
    
    /**
     * Returns the exact class name and the identity hash, also the values of the most often used {@link BeansWrapper}
     * configuration properties, also if which (if any) shared class introspection cache it uses.
     *  
     * @since 2.3.21
     */
    @Override
    public String toString() {
        final String propsStr = toPropertiesString();
        return ClassUtil.getShortClassNameOfObject(this) + "@" + System.identityHashCode(this)
                + "(" + incompatibleImprovements + ", "
                + (propsStr.length() != 0 ? propsStr + ", ..." : "")
                + ")";
    }
    
    /**
     * Returns the name-value pairs that describe the configuration of this {@link BeansWrapper}; called from
     * {@link #toString()}. The expected format is like {@code "foo=bar, baaz=wombat"}. When overriding this, you should
     * call the super method, and then insert the content before it with a following {@code ", "}, or after it with a
     * preceding {@code ", "}.
     * 
     * @since 2.3.22
     */
    protected String toPropertiesString() {
        // Start with "simpleMapWrapper", because the override in DefaultObjectWrapper expects it to be there!
        return "simpleMapWrapper=" + simpleMapWrapper + ", "
               + "exposureLevel=" + classIntrospector.getExposureLevel() + ", "
               + "exposeFields=" + classIntrospector.getExposeFields() + ", "
               + "preferIndexedReadMethod=" + preferIndexedReadMethod + ", "
               + "treatDefaultMethodsAsBeanMembers="
               + classIntrospector.getTreatDefaultMethodsAsBeanMembers() + ", "
               + "sharedClassIntrospCache="
               + (classIntrospector.isShared() ? "@" + System.identityHashCode(classIntrospector) : "none");
    }

    /**
     * Used for
     * {@link MethodAppearanceFineTuner#process}
     * to store the results; see there.
     */
    static public final class MethodAppearanceDecision {
        private PropertyDescriptor exposeAsProperty;
        private boolean methodInsteadOfPropertyValueBeforeCall;
        private boolean replaceExistingProperty;
        private String exposeMethodAs;
        private boolean methodShadowsProperty;

        /**
         * @param appliedZeroArgumentNonVoidMethodPolicy
         *      {@code null} if this is not a zero argument method with non-void return type.
         */
        void setDefaults(Method m, ZeroArgumentNonVoidMethodPolicy appliedZeroArgumentNonVoidMethodPolicy) {
            if (appliedZeroArgumentNonVoidMethodPolicy != null
                    && appliedZeroArgumentNonVoidMethodPolicy != ZeroArgumentNonVoidMethodPolicy.METHOD_ONLY) {
                try {
                    exposeAsProperty = new PropertyDescriptor(m.getName(), m, null);
                } catch (IntrospectionException e) {
                    throw new BugException("Failed to create PropertyDescriptor for " + m, e);
                }
                methodInsteadOfPropertyValueBeforeCall = appliedZeroArgumentNonVoidMethodPolicy ==
                        ZeroArgumentNonVoidMethodPolicy.BOTH_PROPERTY_AND_METHOD;
            } else {
                exposeAsProperty = null;
                methodInsteadOfPropertyValueBeforeCall = false;
            }
            exposeMethodAs = appliedZeroArgumentNonVoidMethodPolicy != ZeroArgumentNonVoidMethodPolicy.PROPERTY_ONLY
                    ? m.getName() : null;
            methodShadowsProperty = true;
            replaceExistingProperty = false;
        }
        
        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}. 
         */
        public PropertyDescriptor getExposeAsProperty() {
            return exposeAsProperty;
        }
        
        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}.
         * Note that you may also want to call
         * {@link #setMethodShadowsProperty(boolean) setMethodShadowsProperty(false)} when you call this. 
         */
        public void setExposeAsProperty(PropertyDescriptor exposeAsProperty) {
            this.exposeAsProperty = exposeAsProperty;
        }

        /**
         * Getter pair of {@link #setReplaceExistingProperty(boolean)}.
         * 
         * @since 2.3.28
         */
        public boolean getReplaceExistingProperty() {
            return replaceExistingProperty;
        }

        /**
         * If {@link #getExposeAsProperty()} is non-{@code null}, and a {@link PropertyDescriptor} with the same
         * property name was already added to the class introspection data, this decides if that will be replaced
         * with the {@link PropertyDescriptor} returned by {@link #getExposeAsProperty()}. The default is {@code false},
         * that is, the old {@link PropertyDescriptor} is kept, and the new one is ignored.
         * JavaBean properties discovered with the standard (non-{@link MethodAppearanceFineTuner}) mechanism
         * are added before those created by the {@link MethodAppearanceFineTuner}, so with this you can decide if a
         * real JavaBeans property can be replaced by the "fake" one created with
         * {@link #setExposeAsProperty(PropertyDescriptor)}.
         * 
         * @since 2.3.28
         */
        public void setReplaceExistingProperty(boolean overrideExistingProperty) {
            this.replaceExistingProperty = overrideExistingProperty;
        }

        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}. 
         */
        public String getExposeMethodAs() {
            return exposeMethodAs;
        }
        
        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}. 
         */
        public void setExposeMethodAs(String exposeAsMethod) {
            this.exposeMethodAs = exposeAsMethod;
        }
        
        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}. 
         */
        public boolean getMethodShadowsProperty() {
            return methodShadowsProperty;
        }
        
        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}. 
         */
        public void setMethodShadowsProperty(boolean shadowEarlierProperty) {
            this.methodShadowsProperty = shadowEarlierProperty;
        }

        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}.
         *
         * @since 2.3.33
         */
        public boolean isMethodInsteadOfPropertyValueBeforeCall() {
            return methodInsteadOfPropertyValueBeforeCall;
        }

        /**
         * See in the documentation of {@link MethodAppearanceFineTuner#process}.
         *
         * @since 2.3.33
         */
        public void setMethodInsteadOfPropertyValueBeforeCall(boolean methodInsteadOfPropertyValueBeforeCall) {
            this.methodInsteadOfPropertyValueBeforeCall = methodInsteadOfPropertyValueBeforeCall;
        }
    }
    
    /**
     * Used for {@link MethodAppearanceFineTuner#process} as input parameter; see there.
     */
    static public final class MethodAppearanceDecisionInput {
        private Method method;
        private Class<?> containingClass;
        
        void setMethod(Method method) {
            this.method = method;
        }
        
        void setContainingClass(Class<?> containingClass) {
            this.containingClass = containingClass;
        }

        public Method getMethod() {
            return method;
        }

        public Class/*<?>*/ getContainingClass() {
            return containingClass;
        }
        
    }

}
