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

import java.util.Date;
import java.util.List;

import freemarker.ext.beans.BeanModel;
import freemarker.ext.beans.OverloadedMethodsModel;
import freemarker.ext.beans.SimpleMethodModel;
import freemarker.ext.beans._BeansAPI;
import freemarker.template.SimpleDate;
import freemarker.template.SimpleNumber;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateCollectionModelEx;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateHashModelEx;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelWithAPISupport;
import freemarker.template.TemplateNodeModel;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;
import freemarker.template.TemplateTransformModel;
import freemarker.template._TemplateAPI;

/**
 * A holder for builtins that didn't fit into any other category.
 */
class BuiltInsForMultipleTypes {

    static class cBI extends AbstractCBI implements ICIChainMember {
        
        static class BIBeforeICE2d3d21 extends AbstractCBI {

            @Override
            protected TemplateModel formatNumber(Environment env, TemplateModel model) throws TemplateModelException {
                Number num = EvalUtil.modelToNumber((TemplateNumberModel) model, target);
                if (num instanceof Integer || num instanceof Long) {
                    // Accelerate these fairly common cases
                    return new SimpleScalar(num.toString());
                } else {
                    return new SimpleScalar(env.getCNumberFormat().format(num));
                }
            }
            
        }
        
        private final BIBeforeICE2d3d21 prevICIObj = new BIBeforeICE2d3d21();

        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel model = target.eval(env);
            if (model instanceof TemplateNumberModel) {
                return formatNumber(env, model);
            } else if (model instanceof TemplateBooleanModel) {
                return new SimpleScalar(((TemplateBooleanModel) model).getAsBoolean()
                        ? MiscUtil.C_TRUE : MiscUtil.C_FALSE);
            } else {
                throw new UnexpectedTypeException(
                        target, model,
                        "number or boolean", new Class[] { TemplateNumberModel.class, TemplateBooleanModel.class },
                        env);
            }
        }

        @Override
        protected TemplateModel formatNumber(Environment env, TemplateModel model) throws TemplateModelException {
            Number num = EvalUtil.modelToNumber((TemplateNumberModel) model, target);
            if (num instanceof Integer || num instanceof Long) {
                // Accelerate these fairly common cases
                return new SimpleScalar(num.toString());
            } else if (num instanceof Double) {
                double n = num.doubleValue();
                if (n == Double.POSITIVE_INFINITY) {
                    return new SimpleScalar("INF");
                }
                if (n == Double.NEGATIVE_INFINITY) {
                    return new SimpleScalar("-INF");
                }
                if (Double.isNaN(n)) {
                    return new SimpleScalar("NaN");
                }
                // Deliberately falls through
            } else if (num instanceof Float) {
                float n = num.floatValue();
                if (n == Float.POSITIVE_INFINITY) {
                    return new SimpleScalar("INF");
                }
                if (n == Float.NEGATIVE_INFINITY) {
                    return new SimpleScalar("-INF");
                }
                if (Float.isNaN(n)) {
                    return new SimpleScalar("NaN");
                }
                // Deliberately falls through
            }
        
            return new SimpleScalar(env.getCNumberFormat().format(num));
        }

        public int getMinimumICIVersion() {
            return _TemplateAPI.VERSION_INT_2_3_21;
        }
        
        public Object getPreviousICIChainMember() {
            return prevICIObj;
        }
        
    }

    static class dateBI extends BuiltIn {
        private class DateParser
        implements
            TemplateDateModel,
            TemplateMethodModel,
            TemplateHashModel {
            private final String text;
            private final Environment env;
            private final TemplateDateFormat defaultFormat;
            private TemplateDateModel cachedValue;
            
            DateParser(String text, Environment env)
            throws TemplateException {
                this.text = text;
                this.env = env;
                this.defaultFormat = env.getTemplateDateFormat(dateType, Date.class, target, false);
            }
            
            public Object exec(List args) throws TemplateModelException {
                checkMethodArgCount(args, 0, 1);
                return args.size() == 0 ? getAsDateModel() : get((String) args.get(0));
            }
            
            public TemplateModel get(String pattern) throws TemplateModelException {
                TemplateDateFormat format;
                try {
                    format = env.getTemplateDateFormat(pattern, dateType, Date.class, target, dateBI.this, true);
                } catch (TemplateException e) {
                    // `e` should always be a TemplateModelException here, but to be sure: 
                    throw _CoreAPI.ensureIsTemplateModelException("Failed to get format", e); 
                }
                return toTemplateDateModel(parse(format));
            }

            private TemplateDateModel toTemplateDateModel(Object date) throws _TemplateModelException {
                if (date instanceof Date) {
                    return new SimpleDate((Date) date, dateType);
                } else {
                    TemplateDateModel tm = (TemplateDateModel) date;
                    if (tm.getDateType() != dateType) {
                        throw new _TemplateModelException("The result of the parsing was of the wrong date type.");
                    }
                    return tm;
                }
            }

            private TemplateDateModel getAsDateModel() throws TemplateModelException {
                if (cachedValue == null) {
                    cachedValue = toTemplateDateModel(parse(defaultFormat));
                }
                return cachedValue;
            }
            
            public Date getAsDate() throws TemplateModelException {
                return getAsDateModel().getAsDate();
            }
    
            public int getDateType() {
                return dateType;
            }
    
            public boolean isEmpty() {
                return false;
            }
    
            private Object parse(TemplateDateFormat df)
            throws TemplateModelException {
                try {
                    return df.parse(text, dateType);
                } catch (TemplateValueFormatException e) {
                    throw new _TemplateModelException(e,
                            "The string doesn't match the expected date/time/date-time format. "
                            + "The string to parse was: ", new _DelayedJQuote(text), ". ",
                            "The expected format was: ", new _DelayedJQuote(df.getDescription()), ".",
                            e.getMessage() != null ? "\nThe nested reason given follows:\n" : "",
                            e.getMessage() != null ? e.getMessage() : "");
                }
            }
            
        }
        
        private final int dateType;
        
        dateBI(int dateType) {
            this.dateType = dateType;
        }
        
        @Override
        TemplateModel _eval(Environment env)
                throws TemplateException {
            TemplateModel model = target.eval(env);
            if (model instanceof TemplateDateModel) {
                TemplateDateModel dmodel = (TemplateDateModel) model;
                int dtype = dmodel.getDateType();
                // Any date model can be coerced into its own type
                if (dateType == dtype) {
                    return model;
                }
                // unknown and datetime can be coerced into any date type
                if (dtype == TemplateDateModel.UNKNOWN || dtype == TemplateDateModel.DATETIME) {
                    return new SimpleDate(dmodel.getAsDate(), dateType);
                }
                throw new _MiscTemplateException(this,
                            "Cannot convert ", TemplateDateModel.TYPE_NAMES.get(dtype),
                            " to ", TemplateDateModel.TYPE_NAMES.get(dateType));
            }
            // Otherwise, interpret as a string and attempt 
            // to parse it into a date.
            String s = target.evalAndCoerceToPlainText(env);
            return new DateParser(s, env);
        }

    }

    static class apiBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            if (!env.isAPIBuiltinEnabled()) {
                throw new _MiscTemplateException(this,
                        "Can't use ?api, because the \"", Configurable.API_BUILTIN_ENABLED_KEY,
                        "\" configuration setting is false. Think twice before you set it to true though. Especially, "
                        + "it shouldn't abussed for modifying Map-s and Collection-s.");
            }
            final TemplateModel tm = target.eval(env);
            if (!(tm instanceof TemplateModelWithAPISupport)) {
                target.assertNonNull(tm, env);
                throw new APINotSupportedTemplateException(env, target, tm);
            }
            return ((TemplateModelWithAPISupport) tm).getAPI();
        }
    }

    static class has_apiBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            final TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return tm instanceof TemplateModelWithAPISupport ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }
    
    static class is_booleanBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateBooleanModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_collectionBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateCollectionModel) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_collection_exBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateCollectionModelEx) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_dateLikeBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateDateModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_dateOfTypeBI extends BuiltIn {
        
        private final int dateType;
        
        is_dateOfTypeBI(int dateType) {
            this.dateType = dateType;
        }

        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateDateModel) && ((TemplateDateModel) tm).getDateType() == dateType
                ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_directiveBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            // [2.4] WRONG: it also had to check Macro.isFunction()
            return (tm instanceof TemplateTransformModel || tm instanceof BoundCallable
                    || tm instanceof TemplateDirectiveModel) ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_enumerableBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateSequenceModel || tm instanceof TemplateCollectionModel)
                    && (_TemplateAPI.getTemplateLanguageVersionAsInt(this) < _TemplateAPI.VERSION_INT_2_3_21
                        // These implement TemplateSequenceModel, yet they can't be #list-ed:
                        || !(tm instanceof SimpleMethodModel || tm instanceof OverloadedMethodsModel))
                    ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_hash_exBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateHashModelEx) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_hashBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateHashModel) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_indexableBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateSequenceModel) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_macroBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            // WRONG: it also had to check Macro.isFunction()
            return (tm instanceof BoundCallable)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_markup_outputBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateMarkupOutputModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }
    
    static class is_methodBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateMethodModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_nodeBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateNodeModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_numberBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateNumberModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_sequenceBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateSequenceModel
                        && (
                            !(tm instanceof OverloadedMethodsModel || tm instanceof SimpleMethodModel)
                            || !env.isIcI2324OrLater())
                        )
                        ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_stringBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateScalarModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class is_transformBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            target.assertNonNull(tm, env);
            return (tm instanceof TemplateTransformModel)  ?
                TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
        }
    }

    static class namespaceBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel tm = target.eval(env);
            if (!(tm instanceof BoundCallable)) {
                throw new UnexpectedTypeException(
                        target, tm,
                        "macro or function", new Class[] { BoundCallable.class },
                        env);
            } else {
                return ((BoundCallable) tm).getNamespace();
            }
        }
    }

    static class sizeBI extends BuiltIn {
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel model = target.eval(env);

            final int size;
            if (model instanceof TemplateSequenceModel) {
                size = ((TemplateSequenceModel) model).size();
            } else if (model instanceof TemplateCollectionModelEx) {
                size = ((TemplateCollectionModelEx) model).size();
            } else if (model instanceof TemplateHashModelEx) {
                size = ((TemplateHashModelEx) model).size();
            } else {
                throw new UnexpectedTypeException(
                        target, model,
                        "extended-hash or sequence or extended collection",
                        new Class[] {
                                TemplateHashModelEx.class,
                                TemplateSequenceModel.class,
                                TemplateCollectionModelEx.class
                        },
                        env);
            }
            return new SimpleNumber(size);
        }
    }
    
    static class stringBI extends BuiltIn {
        
        private class BooleanFormatter
        implements 
            TemplateScalarModel, 
            TemplateMethodModel {
            private final TemplateBooleanModel bool;
            private final Environment env;
            
            BooleanFormatter(TemplateBooleanModel bool, Environment env) {
                this.bool = bool;
                this.env = env;
            }
    
            public Object exec(List args) throws TemplateModelException {
                checkMethodArgCount(args, 2);
                return new SimpleScalar((String) args.get(bool.getAsBoolean() ? 0 : 1));
            }
    
            public String getAsString() throws TemplateModelException {
                // Boolean should have come first... but that change would be non-BC. 
                if (bool instanceof TemplateScalarModel) {
                    return ((TemplateScalarModel) bool).getAsString();
                } else {
                    try {
                        return env.formatBoolean(bool.getAsBoolean(), true);
                    } catch (TemplateException e) {
                        throw new TemplateModelException(e);
                    }
                }
            }
        }
    
        private class DateFormatter
        implements
            TemplateScalarModel,
            TemplateHashModel,
            TemplateMethodModel {
            private final TemplateDateModel dateModel;
            private final Environment env;
            private final TemplateDateFormat defaultFormat;
            private String cachedValue;
    
            DateFormatter(TemplateDateModel dateModel, Environment env)
            throws TemplateException {
                this.dateModel = dateModel;
                this.env = env;
                
                final int dateType = dateModel.getDateType();
                this.defaultFormat = dateType == TemplateDateModel.UNKNOWN
                        ? null  // Lazy unknown type error in getAsString()
                        : env.getTemplateDateFormat(
                                dateType, EvalUtil.modelToDate(dateModel, target).getClass(), target, true);
            }
    
            public Object exec(List args) throws TemplateModelException {
                checkMethodArgCount(args, 1);
                return formatWith((String) args.get(0));
            }

            public TemplateModel get(String key)
            throws TemplateModelException {
                return formatWith(key);
            }

            private TemplateModel formatWith(String key)
            throws TemplateModelException {
                try {
                    return new SimpleScalar(env.formatDateToPlainText(dateModel, key, target, stringBI.this, true));
                } catch (TemplateException e) {
                    // `e` should always be a TemplateModelException here, but to be sure: 
                    throw _CoreAPI.ensureIsTemplateModelException("Failed to format value", e); 
                }
            }
            
            public String getAsString()
            throws TemplateModelException {
                if (cachedValue == null) {
                    if (defaultFormat == null) {
                        if (dateModel.getDateType() == TemplateDateModel.UNKNOWN) {
                            throw MessageUtil.newCantFormatUnknownTypeDateException(target, null);
                        } else {
                            throw new BugException();
                        }
                    }
                    try {
                        cachedValue = EvalUtil.assertFormatResultNotNull(defaultFormat.formatToPlainText(dateModel));
                    } catch (TemplateValueFormatException e) {
                        try {
                            throw MessageUtil.newCantFormatDateException(defaultFormat, target, e, true);
                        } catch (TemplateException e2) {
                            // `e` should always be a TemplateModelException here, but to be sure: 
                            throw _CoreAPI.ensureIsTemplateModelException("Failed to format date/time/datetime", e2); 
                        }
                    }
                }
                return cachedValue;
            }
    
            public boolean isEmpty() {
                return false;
            }
        }
        
        private class NumberFormatter
        implements
            TemplateScalarModel,
            TemplateHashModel,
            TemplateMethodModel {
            private final TemplateNumberModel numberModel;
            private final Number number;
            private final Environment env;
            private final TemplateNumberFormat defaultFormat;
            private String cachedValue;
    
            NumberFormatter(TemplateNumberModel numberModel, Environment env) throws TemplateException {
                this.env = env;
                
                // As we format lazily, we need a snapshot of the format inputs:
                this.numberModel = numberModel;
                number = EvalUtil.modelToNumber(numberModel, target);  // for BackwardCompatibleTemplateNumberFormat-s
                try {
                    defaultFormat = env.getTemplateNumberFormat(stringBI.this, true);
                } catch (TemplateException e) {
                    // `e` should always be a TemplateModelException here, but to be sure: 
                    throw _CoreAPI.ensureIsTemplateModelException("Failed to get default number format", e); 
                }
            }
    
            public Object exec(List args) throws TemplateModelException {
                checkMethodArgCount(args, 1);
                return get((String) args.get(0));
            }
    
            public TemplateModel get(String key) throws TemplateModelException {
                TemplateNumberFormat format;
                try {
                    format = env.getTemplateNumberFormat(key, stringBI.this, true);
                } catch (TemplateException e) {
                    // `e` should always be a TemplateModelException here, but to be sure: 
                    throw _CoreAPI.ensureIsTemplateModelException("Failed to get number format", e); 
                }
                
                String result;
                try {
                    if (format instanceof BackwardCompatibleTemplateNumberFormat) {
                        result = env.formatNumberToPlainText(number, (BackwardCompatibleTemplateNumberFormat) format, target);
                    } else {
                        result = env.formatNumberToPlainText(numberModel, format, target, true);
                    }
                } catch (TemplateException e) {
                    // `e` should always be a TemplateModelException here, but to be sure: 
                    throw _CoreAPI.ensureIsTemplateModelException("Failed to format number", e); 
                }
                
                return new SimpleScalar(result);
            }
            
            public String getAsString() throws TemplateModelException {
                if (cachedValue == null) {
                    try {
                        if (defaultFormat instanceof BackwardCompatibleTemplateNumberFormat) {
                            cachedValue = env.formatNumberToPlainText(
                                    number, (BackwardCompatibleTemplateNumberFormat) defaultFormat, target);
                        } else {
                            cachedValue = env.formatNumberToPlainText(numberModel, defaultFormat, target, true);
                        }
                    } catch (TemplateException e) {
                        // `e` should always be a TemplateModelException here, but to be sure: 
                        throw _CoreAPI.ensureIsTemplateModelException("Failed to format number", e); 
                    }
                }
                return cachedValue;
            }
    
            public boolean isEmpty() {
                return false;
            }
        }
    
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel model = target.eval(env);
            if (model instanceof TemplateNumberModel) {
                TemplateNumberModel numberModel = (TemplateNumberModel) model;
                Number num = EvalUtil.modelToNumber(numberModel, target);
                return new NumberFormatter(numberModel, env);
            } else if (model instanceof TemplateDateModel) {
                TemplateDateModel dm = (TemplateDateModel) model;
                return new DateFormatter(dm, env);
            } else if (model instanceof SimpleScalar) {
                return model;
            } else if (model instanceof TemplateBooleanModel) {
                return new BooleanFormatter((TemplateBooleanModel) model, env);
            } else if (model instanceof TemplateScalarModel) {
                return new SimpleScalar(((TemplateScalarModel) model).getAsString());
            } else if (env.isClassicCompatible() && model instanceof BeanModel) {
                return new SimpleScalar(_BeansAPI.getAsClassicCompatibleString((BeanModel) model));
            } else {            
                throw new UnexpectedTypeException(
                        target, model,
                        "number, date, boolean or string",
                        new Class[] {
                            TemplateNumberModel.class, TemplateDateModel.class, TemplateBooleanModel.class,
                            TemplateScalarModel.class
                        },
                        env);
            }
        }
    }

    // Can't be instantiated
    private BuiltInsForMultipleTypes() { }

    static abstract class AbstractCBI extends BuiltIn {
        
        @Override
        TemplateModel _eval(Environment env) throws TemplateException {
            TemplateModel model = target.eval(env);
            if (model instanceof TemplateNumberModel) {
                return formatNumber(env, model);
            } else if (model instanceof TemplateBooleanModel) {
                return new SimpleScalar(((TemplateBooleanModel) model).getAsBoolean()
                        ? MiscUtil.C_TRUE : MiscUtil.C_FALSE);
            } else {
                throw new UnexpectedTypeException(
                        target, model,
                        "number or boolean", new Class[] { TemplateNumberModel.class, TemplateBooleanModel.class },
                        env);
            }
        }
    
        protected abstract TemplateModel formatNumber(Environment env, TemplateModel model) throws TemplateModelException;
        
    }

}
