/*
 * 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.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import freemarker.cache.AndMatcher;
import freemarker.cache.ConditionalTemplateConfigurationFactory;
import freemarker.cache.FileExtensionMatcher;
import freemarker.cache.FileNameGlobMatcher;
import freemarker.cache.FirstMatchTemplateConfigurationFactory;
import freemarker.cache.MergingTemplateConfigurationFactory;
import freemarker.cache.NotMatcher;
import freemarker.cache.OrMatcher;
import freemarker.cache.PathGlobMatcher;
import freemarker.cache.PathRegexMatcher;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.SimpleObjectWrapper;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.Version;
import freemarker.template.utility.ClassUtil;
import freemarker.template.utility.StringUtil;
import freemarker.template.utility.WriteProtectable;

/**
 * Don't use this; used internally by FreeMarker, might changes without notice.
 * 
 * Evaluates object builder expressions used in configuration {@link Properties}.
 * It should be replaced with FTL later (when it was improved to be practical for this), so the syntax should be
 * a subset of the future FTL syntax. This is also why this syntax is restrictive; it shouldn't accept anything that
 * FTL will not.
 */
// Java 5: use generics for expectedClass
// Java 5: Introduce ObjectBuilder interface
public class _ObjectBuilderSettingEvaluator {
    
    private static final String INSTANCE_FIELD_NAME = "INSTANCE";

    private static final String BUILD_METHOD_NAME = "build";

    private static final String BUILDER_CLASS_POSTFIX = "Builder";

    private static Map<String,String> SHORTHANDS;
    
    private static final Object VOID = new Object();

    private final String src;
    private final Class expectedClass;
    private final boolean allowNull;
    private final _SettingEvaluationEnvironment env;

    // Parser state:
    private int pos;
    
    // Parsing results:
    private boolean modernMode = false;
    
    private _ObjectBuilderSettingEvaluator(
            String src, int pos, Class expectedClass, boolean allowNull, _SettingEvaluationEnvironment env) {
        this.src = src;
        this.pos = pos;
        this.expectedClass = expectedClass;
        this.allowNull = allowNull;
        this.env = env;
    }

    public static Object eval(String src, Class expectedClass, boolean allowNull, _SettingEvaluationEnvironment env)
            throws _ObjectBuilderSettingEvaluationException,
            ClassNotFoundException, InstantiationException, IllegalAccessException {
        return new _ObjectBuilderSettingEvaluator(src, 0, expectedClass, allowNull, env).eval();
    }

    /**
     * Used for getting a list of setting assignments (like {@code (x=1, y=2)}) from an existing string, and apply it on
     * an existing bean.
     * 
     * @return The location of the next character to process.
     */
    public static int configureBean(
            String argumentListSrc, int posAfterOpenParen, Object bean, _SettingEvaluationEnvironment env)
            throws _ObjectBuilderSettingEvaluationException,
            ClassNotFoundException, InstantiationException, IllegalAccessException {
        return new _ObjectBuilderSettingEvaluator(
                argumentListSrc, posAfterOpenParen, bean.getClass(), true, env).configureBean(bean);
    }
    
    private Object eval() throws _ObjectBuilderSettingEvaluationException,
            ClassNotFoundException, InstantiationException, IllegalAccessException {
        Object value;
        
        skipWS();
        try {
            value = ensureEvaled(fetchValue(false, true, false, true));
        } catch (LegacyExceptionWrapperSettingEvaluationExpression e) {
            e.rethrowLegacy();
            value = null; // newer reached
        }
        skipWS();
        
        if (pos != src.length()) {
            throw new _ObjectBuilderSettingEvaluationException("end-of-expression", src, pos);
        }
        
        if (value == null && !allowNull) {
            throw new _ObjectBuilderSettingEvaluationException("Value can't be null.");
        }
        if (value != null && !expectedClass.isInstance(value)) {
            throw new _ObjectBuilderSettingEvaluationException("The resulting object (of class "
                    + value.getClass() + ") is not a(n) " + expectedClass.getName() + ".");
        }
        
        return value;
    }
    
    private int configureBean(Object bean) throws _ObjectBuilderSettingEvaluationException,
            ClassNotFoundException, InstantiationException, IllegalAccessException {
        final PropertyAssignmentsExpression propAssignments = new PropertyAssignmentsExpression(bean);
        fetchParameterListInto(propAssignments);
        skipWS();
        propAssignments.eval();
        return pos;
    }

    private Object ensureEvaled(Object value) throws _ObjectBuilderSettingEvaluationException {
        return value instanceof SettingExpression ? ((SettingExpression) value).eval() : value;
    }

    private Object fetchBuilderCall(boolean optional, boolean topLevel)
            throws _ObjectBuilderSettingEvaluationException {
        int startPos = pos;
        
        BuilderCallExpression exp = new BuilderCallExpression();
        // We need the canBeStaticField/mustBeStaticFiled complication to deal with legacy syntax where parentheses
        // weren't required for constructor calls.
        exp.canBeStaticField = true;
        
        final String fetchedClassName = fetchClassName(optional);
        {
            if (fetchedClassName == null) {
                if (!optional) {
                    throw new _ObjectBuilderSettingEvaluationException("class name", src, pos);
                }
                return VOID;
            }
            exp.className = shorthandToFullQualified(fetchedClassName);
            if (!fetchedClassName.equals(exp.className)) {
                // Before 2.3.21 only full-qualified class names were allowed
                modernMode = true;
                exp.canBeStaticField = false;
            }
        }
        
        skipWS();
        
        char openParen = fetchOptionalChar("(");
        // Only the top-level expression can omit the "(...)"
        if (openParen == 0 && !topLevel) {
            if (fetchedClassName.indexOf('.') != -1) {
                exp.mustBeStaticField = true;
            } else {
                pos = startPos;
                return VOID;
            }
        }
    
        if (openParen != 0) {
            fetchParameterListInto(exp);
            exp.canBeStaticField = false;
        }
        
        return exp;
    }

    private void fetchParameterListInto(ExpressionWithParameters exp) throws _ObjectBuilderSettingEvaluationException {
        // Before 2.3.21 there was no parameter list
        modernMode = true;
        
        skipWS();
        if (fetchOptionalChar(")") != ')') { 
            do {
                skipWS();
                
                Object paramNameOrValue = fetchValue(false, false, true, false);
                if (paramNameOrValue != VOID) {
                    skipWS();
                    if (paramNameOrValue instanceof Name) {
                        exp.namedParamNames.add(((Name) paramNameOrValue).name);
                        
                        skipWS();
                        fetchRequiredChar("=");
                        skipWS();
                        
                        Object paramValue = fetchValue(false, false, true, true);
                        exp.namedParamValues.add(ensureEvaled(paramValue));
                    } else {
                        if (!exp.namedParamNames.isEmpty()) {
                            throw new _ObjectBuilderSettingEvaluationException(
                                    "Positional parameters must precede named parameters");
                        }
                        if (!exp.getAllowPositionalParameters()) {
                            throw new _ObjectBuilderSettingEvaluationException(
                                    "Positional parameters not supported here");
                        }
                        exp.positionalParamValues.add(ensureEvaled(paramNameOrValue));
                    }
                    
                    skipWS();
                }
            } while (fetchRequiredChar(",)") == ',');
        }
    }

    private Object fetchValue(boolean optional, boolean topLevel, boolean resultCoerced, boolean resolveVariables)
            throws _ObjectBuilderSettingEvaluationException {
        if (pos < src.length()) {
            Object val = fetchNumberLike(true, resultCoerced);
            if (val != VOID) {
                return val;
            }
    
            val = fetchStringLiteral(true);
            if (val != VOID) {
                return val;
            }

            val = fetchListLiteral(true);
            if (val != VOID) {
                return val;
            }

            val = fetchMapLiteral(true);
            if (val != VOID) {
                return val;
            }
            
            val = fetchBuilderCall(true, topLevel);
            if (val != VOID) {
                return val;
            }
            
            String name = fetchSimpleName(true);
            if (name != null) {
                val = keywordToValueOrVoid(name);
                if (val != VOID) {
                    return val;
                }
                
                if (resolveVariables) {
                    // Not supported currently...
                    throw new _ObjectBuilderSettingEvaluationException("Can't resolve variable reference: " + name);
                } else {
                    return new Name(name);
                }
            }
        }
        
        if (optional) {
            return VOID;
        } else {
            throw new _ObjectBuilderSettingEvaluationException("value or name", src, pos);
        }
    }

    private boolean isKeyword(String name) {
        return keywordToValueOrVoid(name) != VOID;
    }
    
    private Object keywordToValueOrVoid(String name) {
        if (name.equals("true")) return Boolean.TRUE;
        if (name.equals("false")) return Boolean.FALSE;
        if (name.equals("null")) return null;
        return VOID;
    }

    private String fetchSimpleName(boolean optional) throws _ObjectBuilderSettingEvaluationException {
        char c = pos < src.length() ? src.charAt(pos) : 0;
        if (!isIdentifierStart(c)) {
            if (optional) {
                return null;
            } else {
                throw new _ObjectBuilderSettingEvaluationException("class name", src, pos);
            }
        }
        int startPos = pos;
        pos++;
        
        seekClassNameEnd: while (true) {
            if (pos == src.length()) {
                break seekClassNameEnd;
            }
            c = src.charAt(pos);
            if (!isIdentifierMiddle(c)) {
                break seekClassNameEnd;
            }
            pos++;
        }
        
        return src.substring(startPos, pos);
    }

    private String fetchClassName(boolean optional) throws _ObjectBuilderSettingEvaluationException {
        int startPos = pos;
        StringBuilder sb = new StringBuilder();
        do {
            String name = fetchSimpleName(true);
            if (name == null) {
                if (!optional) {
                    throw new _ObjectBuilderSettingEvaluationException("name", src, pos);
                } else {
                    pos = startPos;
                    return null;
                }
            }
            sb.append(name);
            
            skipWS();
            
            if (pos >= src.length() || src.charAt(pos) != '.') {
                break;
            }
            sb.append('.');
            pos++;
            
            skipWS();
        } while (true);
        
        String className = sb.toString();
        if (isKeyword(className)) {
            pos = startPos;
            return null;
        }
        return className;
    }

    private Object fetchNumberLike(boolean optional, boolean resultCoerced)
            throws _ObjectBuilderSettingEvaluationException {
        int startPos = pos;
        boolean isVersion = false;
        boolean hasDot = false;
        seekTokenEnd: while (true) {
            if (pos == src.length()) {
                break seekTokenEnd;
            }
            char c = src.charAt(pos);
            if (c == '.') {
                if (hasDot) {
                    // More than one dot
                    isVersion = true;
                } else {
                    hasDot = true;
                }
            } else if (!(isASCIIDigit(c) || c == '-')) {
                break seekTokenEnd;
            }
            pos++;
        }
        
        if (startPos == pos) {
            if (optional) {
                return VOID;
            } else {
                throw new _ObjectBuilderSettingEvaluationException("number-like", src, pos);
            }
        }
        
        String numStr = src.substring(startPos, pos);
        if (isVersion) {
            try {
                return new Version(numStr);
            } catch (IllegalArgumentException e) {
                throw new _ObjectBuilderSettingEvaluationException("Malformed version number: " + numStr, e);
            }
        } else {
            // For example, in 1.0f, numStr is "1.0", and typePostfix is "f".
            String typePostfix = null;
            seekTypePostfixEnd: while (true) {
                if (pos == src.length()) {
                    break seekTypePostfixEnd;
                }
                char c = src.charAt(pos);
                if (Character.isLetter(c)) {
                    if (typePostfix == null) {
                        typePostfix = String.valueOf(c);
                    } else {
                        typePostfix += c; 
                    }
                } else {
                    break seekTypePostfixEnd;
                }
                pos++;
            }
            
            try {
                if (numStr.endsWith(".")) {
                    throw new NumberFormatException("A number can't end with a dot");
                }
                if (numStr.startsWith(".") || numStr.startsWith("-.")  || numStr.startsWith("+.")) {
                    throw new NumberFormatException("A number can't start with a dot");
                }

                if (typePostfix == null) {
                    // Auto-detect type
                    if (numStr.indexOf('.') == -1) {
                        BigInteger biNum = new BigInteger(numStr);
                        final int bitLength = biNum.bitLength();  // Doesn't include sign bit
                        if (bitLength <= 31) {
                            return Integer.valueOf(biNum.intValue());
                        } else if (bitLength <= 63) {
                            return Long.valueOf(biNum.longValue());
                        } else {
                            return biNum;
                        }
                    } else {
                        if (resultCoerced) {
                            // The FTL way (BigDecimal is loseless, and it will be coerced to the target type later):
                            return new BigDecimal(numStr);
                        } else {
                            // The Java way (lossy but familiar):
                            return Double.valueOf(numStr);
                        }
                    }
                } else { // Has explicitly specified type
                    if (typePostfix.equalsIgnoreCase("l")) {
                        return Long.valueOf(numStr);
                    } else if (typePostfix.equalsIgnoreCase("bi")) {
                        return new BigInteger(numStr);
                    } else if (typePostfix.equalsIgnoreCase("bd")) {
                        return new BigDecimal(numStr);
                    } else if (typePostfix.equalsIgnoreCase("d")) {
                        return Double.valueOf(numStr);
                    } else if (typePostfix.equalsIgnoreCase("f")) {
                        return Float.valueOf(numStr);
                    } else {
                        throw new _ObjectBuilderSettingEvaluationException(
                                "Unrecognized number type postfix: " + typePostfix);
                    }
                }
                
            } catch (NumberFormatException e) {
                throw new _ObjectBuilderSettingEvaluationException("Malformed number: " + numStr, e);
            }
        }
    }

    private Object fetchStringLiteral(boolean optional) throws _ObjectBuilderSettingEvaluationException {
        int startPos = pos;
        char q = 0;
        boolean afterEscape = false;
        boolean raw = false;
        seekTokenEnd: while (true) {
            if (pos == src.length()) {
                if (q != 0) {
                    // We had an open quotation
                    throw new _ObjectBuilderSettingEvaluationException(String.valueOf(q), src, pos);
                }
                break seekTokenEnd;
            }
            char c = src.charAt(pos);
            if (q == 0) {
                if (c == 'r' && (pos + 1 < src.length())) {
                    // Maybe it's like r"foo\bar"
                    raw = true;
                    c = src.charAt(pos + 1);
                }
                if (c == '\'') {
                    q = '\'';
                } else if (c == '"') {
                    q = '"';
                } else {
                    break seekTokenEnd;
                }
                if (raw) {
                    // because of the preceding "r"
                    pos++;
                }
            } else {
                if (!afterEscape) {
                    if (c == '\\' && !raw) {
                        afterEscape = true;
                    } else if (c == q) {
                        break seekTokenEnd;
                    } else if (c == '{') {
                        char prevC = src.charAt(pos - 1);
                        if (prevC == '$' || prevC == '#') {
                            throw new _ObjectBuilderSettingEvaluationException(
                                    "${...} and #{...} aren't allowed here.");
                        }
                    }
                } else {
                    afterEscape = false;
                }
            }
            pos++;
        }
        if (startPos == pos) {
            if (optional) {
                return VOID;
            } else {
                throw new _ObjectBuilderSettingEvaluationException("string literal", src, pos);
            }
        }
            
        final String sInside = src.substring(startPos + (raw ? 2 : 1), pos);
        try {
            pos++; // skip closing quotation mark
            return raw ? sInside : StringUtil.FTLStringLiteralDec(sInside);
        } catch (ParseException e) {
            throw new _ObjectBuilderSettingEvaluationException("Malformed string literal: " + sInside, e);
        }
    }

    private Object fetchListLiteral(boolean optional) throws _ObjectBuilderSettingEvaluationException {
        if (pos == src.length() || src.charAt(pos) != '[') {
            if (!optional) {
                throw new _ObjectBuilderSettingEvaluationException("[", src, pos);
            }
            return VOID;
        }
        pos++;
        
        ListExpression listExp = new ListExpression();
        
        while (true) {
            skipWS();
            
            if (fetchOptionalChar("]") != 0) {
                return listExp;
            }
            if (listExp.itemCount() != 0) {
                fetchRequiredChar(",");
                skipWS();
            }
            
            listExp.addItem(fetchValue(false, false, false, true));
            
            skipWS();
        }
    }

    private Object fetchMapLiteral(boolean optional) throws _ObjectBuilderSettingEvaluationException {
        if (pos == src.length() || src.charAt(pos) != '{') {
            if (!optional) {
                throw new _ObjectBuilderSettingEvaluationException("{", src, pos);
            }
            return VOID;
        }
        pos++;
        
        MapExpression mapExp = new MapExpression();
        
        while (true) {
            skipWS();
            
            if (fetchOptionalChar("}") != 0) {
                return mapExp;
            }
            if (mapExp.itemCount() != 0) {
                fetchRequiredChar(",");
                skipWS();
            }
            
            Object key = fetchValue(false, false, false, true);
            skipWS();
            fetchRequiredChar(":");
            skipWS();
            Object value = fetchValue(false, false, false, true);
            mapExp.addItem(new KeyValuePair(key, value));
            
            skipWS();
        }
    }
    
    private void skipWS() {
        while (true) {
            if (pos == src.length()) {
                return;
            }
            char c = src.charAt(pos);
            if (!Character.isWhitespace(c)) {
                return;
            }
            pos++;
        }
    }

    private char fetchOptionalChar(String expectedChars) throws _ObjectBuilderSettingEvaluationException {
        return fetchChar(expectedChars, true);
    }
    
    private char fetchRequiredChar(String expectedChars) throws _ObjectBuilderSettingEvaluationException {
        return fetchChar(expectedChars, false);
    }
    
    private char fetchChar(String expectedChars, boolean optional) throws _ObjectBuilderSettingEvaluationException {
        char c = pos < src.length() ? src.charAt(pos) : 0;
        if (expectedChars.indexOf(c) != -1) {
            pos++;
            return c;
        } else if (optional) {
            return 0;
        } else {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < expectedChars.length(); i++) {
                if (i != 0) {
                    sb.append(" or ");
                }
                sb.append(StringUtil.jQuote(expectedChars.substring(i, i + 1)));
            }
            throw new _ObjectBuilderSettingEvaluationException(
                    sb.toString(),
                    src, pos);
        }
    }
    
    private boolean isASCIIDigit(char c) {
        return c >= '0' && c <= '9';
    }

    private boolean isIdentifierStart(char c) {
        return Character.isLetter(c) || c == '_' || c == '$';
    }

    private boolean isIdentifierMiddle(char c) {
        return isIdentifierStart(c) || isASCIIDigit(c);
    }

    private static synchronized String shorthandToFullQualified(String className) {
        if (SHORTHANDS == null) {
            SHORTHANDS = new HashMap/*<String,String>*/();
            
            addWithSimpleName(SHORTHANDS, DefaultObjectWrapper.class);
            addWithSimpleName(SHORTHANDS, BeansWrapper.class);
            addWithSimpleName(SHORTHANDS, SimpleObjectWrapper.class);

            addWithSimpleName(SHORTHANDS, TemplateConfiguration.class);
            
            addWithSimpleName(SHORTHANDS, PathGlobMatcher.class);
            addWithSimpleName(SHORTHANDS, FileNameGlobMatcher.class);
            addWithSimpleName(SHORTHANDS, FileExtensionMatcher.class);
            addWithSimpleName(SHORTHANDS, PathRegexMatcher.class);
            addWithSimpleName(SHORTHANDS, AndMatcher.class);
            addWithSimpleName(SHORTHANDS, OrMatcher.class);
            addWithSimpleName(SHORTHANDS, NotMatcher.class);
            
            addWithSimpleName(SHORTHANDS, ConditionalTemplateConfigurationFactory.class);
            addWithSimpleName(SHORTHANDS, MergingTemplateConfigurationFactory.class);
            addWithSimpleName(SHORTHANDS, FirstMatchTemplateConfigurationFactory.class);

            addWithSimpleName(SHORTHANDS, HTMLOutputFormat.class);
            addWithSimpleName(SHORTHANDS, XHTMLOutputFormat.class);
            addWithSimpleName(SHORTHANDS, XMLOutputFormat.class);
            addWithSimpleName(SHORTHANDS, RTFOutputFormat.class);
            addWithSimpleName(SHORTHANDS, PlainTextOutputFormat.class);
            addWithSimpleName(SHORTHANDS, UndefinedOutputFormat.class);

            addWithSimpleName(SHORTHANDS, DefaultTruncateBuiltinAlgorithm.class);

            addWithSimpleName(SHORTHANDS, Locale.class);
            SHORTHANDS.put("TimeZone", "freemarker.core._TimeZone");
            SHORTHANDS.put("markup", "freemarker.core._Markup");

            // For accessing static fields:
            addWithSimpleName(SHORTHANDS, Configuration.class);
        }
        String fullClassName = SHORTHANDS.get(className);
        return fullClassName == null ? className : fullClassName;
    }
    
    private static void addWithSimpleName(Map map, Class<?> pClass) {
        map.put(pClass.getSimpleName(), pClass.getName());
    }

    private void setJavaBeanProperties(Object bean,
            List/*<String>*/ namedParamNames, List/*<Object>*/ namedParamValues)
            throws _ObjectBuilderSettingEvaluationException {
        if (namedParamNames.isEmpty()) {
            return;
        }
        
        final Class cl = bean.getClass();
        Map/*<String,Method>*/ beanPropSetters;
        try {
            PropertyDescriptor[] propDescs = Introspector.getBeanInfo(cl).getPropertyDescriptors();
            beanPropSetters = new HashMap(propDescs.length * 4 / 3, 1.0f);
            for (int i = 0; i < propDescs.length; i++) {
                PropertyDescriptor propDesc = propDescs[i];
                final Method writeMethod = propDesc.getWriteMethod();
                if (writeMethod != null) {
                    beanPropSetters.put(propDesc.getName(), writeMethod);
                }
            }
        } catch (Exception e) {
            throw new _ObjectBuilderSettingEvaluationException("Failed to inspect " + cl.getName() + " class", e);
        }

        TemplateHashModel beanTM = null;
        for (int i = 0; i < namedParamNames.size(); i++) {
            String name = (String) namedParamNames.get(i);
            if (!beanPropSetters.containsKey(name)) {
                throw new _ObjectBuilderSettingEvaluationException(
                        "The " + cl.getName() + " class has no writeable JavaBeans property called "
                        + StringUtil.jQuote(name) + ".");
            }
            
            Method beanPropSetter = (Method) beanPropSetters.put(name, null);
            if (beanPropSetter == null) {
                    throw new _ObjectBuilderSettingEvaluationException(
                            "JavaBeans property " + StringUtil.jQuote(name) + " is set twice.");
            }
            
            try {
                if (beanTM == null) {
                    TemplateModel wrappedObj = env.getObjectWrapper().wrap(bean);
                    if (!(wrappedObj instanceof TemplateHashModel)) {
                        throw new _ObjectBuilderSettingEvaluationException(
                                "The " + cl.getName() + " class is not a wrapped as TemplateHashModel.");
                    }
                    beanTM = (TemplateHashModel) wrappedObj;
                }
                
                TemplateModel m = beanTM.get(beanPropSetter.getName());
                if (m == null) {
                    throw new _ObjectBuilderSettingEvaluationException(
                            "Can't find " + beanPropSetter + " as FreeMarker method.");
                }
                if (!(m instanceof TemplateMethodModelEx)) {
                    throw new _ObjectBuilderSettingEvaluationException(
                            StringUtil.jQuote(beanPropSetter.getName()) + " wasn't a TemplateMethodModelEx.");
                }
                List/*TemplateModel*/ args = new ArrayList();
                args.add(env.getObjectWrapper().wrap(namedParamValues.get(i)));
                ((TemplateMethodModelEx) m).exec(args);
            } catch (Exception e) {
                throw new _ObjectBuilderSettingEvaluationException(
                        "Failed to set " + StringUtil.jQuote(name), e);
            }
        }
    }

    private static class Name {
        
        public Name(String name) {
            this.name = name;
        }

        private final String name;
    }
    
    private abstract static class SettingExpression {
        abstract Object eval() throws _ObjectBuilderSettingEvaluationException;
    }
    
    private abstract class ExpressionWithParameters extends SettingExpression {
        protected List positionalParamValues = new ArrayList();
        protected List/*<String>*/ namedParamNames = new ArrayList();
        protected List/*<Object>*/ namedParamValues = new ArrayList();
        
        protected abstract boolean getAllowPositionalParameters();
    }
    
    private class ListExpression extends SettingExpression {
        
        private List<Object> items = new ArrayList();
        
        void addItem(Object item) {
            items.add(item);
        }

        public int itemCount() {
            return items.size();
        }

        @Override
        Object eval() throws _ObjectBuilderSettingEvaluationException {
            ArrayList res = new ArrayList(items.size());
            for (Object item : items) {
                res.add(ensureEvaled(item));
            }
            return res;
        }
        
    }
    
    private class MapExpression extends SettingExpression {
        
        private List<KeyValuePair> items = new ArrayList();
        
        void addItem(KeyValuePair item) {
            items.add(item);
        }

        public int itemCount() {
            return items.size();
        }

        @Override
        Object eval() throws _ObjectBuilderSettingEvaluationException {
            LinkedHashMap res = new LinkedHashMap(items.size() * 4 / 3, 1f);
            for (KeyValuePair item : items) {
                Object key = ensureEvaled(item.key);
                if (key == null) {
                    throw new _ObjectBuilderSettingEvaluationException("Map can't use null as key.");
                }
                res.put(key, ensureEvaled(item.value));
            }
            return res;
        }
        
    }
    
    private static class KeyValuePair {
        private final Object key;
        private final Object value;
        
        public KeyValuePair(Object key, Object value) {
            this.key = key;
            this.value = value;
        }
    }
    
    private class BuilderCallExpression extends ExpressionWithParameters {
        private String className;
        private boolean canBeStaticField;
        private boolean mustBeStaticField;
        
        @Override
        Object eval() throws _ObjectBuilderSettingEvaluationException {
            if (mustBeStaticField) {
                if (!canBeStaticField) {
                    throw new BugException();
                }
                return getStaticFieldValue(className);
            }
            
            Class cl;
            
            if (!modernMode) {
                try {
                    try {
                        return ClassUtil.forName(className).newInstance();
                    } catch (InstantiationException e) {
                        throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
                    } catch (IllegalAccessException e) {
                        throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
                    } catch (ClassNotFoundException e) {
                        throw new LegacyExceptionWrapperSettingEvaluationExpression(e);
                    }
                } catch (LegacyExceptionWrapperSettingEvaluationExpression e) {
                    if (!canBeStaticField || className.indexOf('.') == -1) {
                        throw e;
                    }
                    // Silently try to interpret className as static filed, throw the original exception if that fails. 
                    try {
                        return getStaticFieldValue(className);
                    } catch (_ObjectBuilderSettingEvaluationException e2) {
                        throw e;
                    }
                }
            }

            boolean clIsBuilderClass;
            try {
                cl = ClassUtil.forName(className + BUILDER_CLASS_POSTFIX);
                clIsBuilderClass = true;
            } catch (ClassNotFoundException e) {
                clIsBuilderClass = false;
                try {
                    cl = ClassUtil.forName(className);
                } catch (Exception e2) {
                    boolean failedToGetAsStaticField;
                    if (canBeStaticField) {
                        // Try to interpret className as static filed: 
                        try {
                            return getStaticFieldValue(className);
                        } catch (_ObjectBuilderSettingEvaluationException e3) {
                            // Suppress it
                            failedToGetAsStaticField = true;
                        }
                    } else {
                        failedToGetAsStaticField = false;
                    }
                    throw new _ObjectBuilderSettingEvaluationException(
                            "Failed to get class " + StringUtil.jQuote(className)
                            + (failedToGetAsStaticField ? " (also failed to resolve name as static field)" : "")
                            + ".",
                            e2);
                }
            }
            
            if (!clIsBuilderClass && hasNoParameters()) {
                try {
                    Field f = cl.getField(INSTANCE_FIELD_NAME);
                    if ((f.getModifiers() & (Modifier.PUBLIC | Modifier.STATIC))
                            == (Modifier.PUBLIC | Modifier.STATIC)) {
                        return f.get(null);
                    }
                } catch (NoSuchFieldException e) {
                    // Expected
                } catch (Exception e) {
                    throw new _ObjectBuilderSettingEvaluationException(
                            "Error when trying to access " + StringUtil.jQuote(className) + "."
                            + INSTANCE_FIELD_NAME, e);
                }
            }
            
            // Create the object to return or its builder:
            Object constructorResult = callConstructor(cl);
            
            // Named parameters will set JavaBeans properties:
            setJavaBeanProperties(constructorResult, namedParamNames, namedParamValues);

            final Object result;
            if (clIsBuilderClass) {
                result = callBuild(constructorResult);
            } else {
                if (constructorResult instanceof WriteProtectable) {
                    ((WriteProtectable) constructorResult).writeProtect();
                }
                result = constructorResult;
            }
            
            return result;
        }
        
        private Object getStaticFieldValue(String dottedName) throws _ObjectBuilderSettingEvaluationException {
            int lastDotIdx = dottedName.lastIndexOf('.');
            if (lastDotIdx == -1) {
                throw new IllegalArgumentException();
            }
            String className = shorthandToFullQualified(dottedName.substring(0, lastDotIdx));
            String fieldName = dottedName.substring(lastDotIdx + 1);

            Class<?> cl;
            try {
                cl = ClassUtil.forName(className);
            } catch (Exception e) {
                throw new _ObjectBuilderSettingEvaluationException(
                        "Failed to get field's parent class, " + StringUtil.jQuote(className) + ".",
                        e);
            }
            
            Field field;
            try {
                field = cl.getField(fieldName);
            } catch (Exception e) {
                throw new _ObjectBuilderSettingEvaluationException(
                        "Failed to get field " + StringUtil.jQuote(fieldName) + " from class "
                        + StringUtil.jQuote(className) + ".",
                        e);
            }
            
            if ((field.getModifiers() & Modifier.STATIC) == 0) {
                throw new _ObjectBuilderSettingEvaluationException("Referred field isn't static: " + field);
            }
            if ((field.getModifiers() & Modifier.PUBLIC) == 0) {
                throw new _ObjectBuilderSettingEvaluationException("Referred field isn't public: " + field);
            }

            if (field.getName().equals(INSTANCE_FIELD_NAME)) {
                throw new _ObjectBuilderSettingEvaluationException(
                        "The " + INSTANCE_FIELD_NAME + " field is only accessible through pseudo-constructor call: "
                        + className + "()");
            }
            
            try {
                return field.get(null);
            } catch (Exception e) {
                throw new _ObjectBuilderSettingEvaluationException("Failed to get field value: " + field, e);
            }
        }

        private Object callConstructor(Class cl)
                throws _ObjectBuilderSettingEvaluationException {
            if (hasNoParameters()) {
                // No need to create ObjectWrapper
                try {
                    return cl.newInstance();
                } catch (Exception e) {
                    throw new _ObjectBuilderSettingEvaluationException(
                            "Failed to call " + cl.getName() + " 0-argument constructor", e);
                }
            } else {
                BeansWrapper ow = env.getObjectWrapper();
                List/*<TemplateModel>*/ tmArgs = new ArrayList(positionalParamValues.size());
                for (int i = 0; i < positionalParamValues.size(); i++) {
                    try {
                        tmArgs.add(ow.wrap(positionalParamValues.get(i)));
                    } catch (TemplateModelException e) {
                        throw new _ObjectBuilderSettingEvaluationException("Failed to wrap arg #" + (i + 1), e);
                    }
                }
                try {
                    return ow.newInstance(cl, tmArgs);
                } catch (Exception e) {
                    throw new _ObjectBuilderSettingEvaluationException(
                            "Failed to call " + cl.getName() + " constructor", e);
                }
            }
        }

        private Object callBuild(Object constructorResult)
                throws _ObjectBuilderSettingEvaluationException {
            final Class cl = constructorResult.getClass();
            Method buildMethod; 
            try {
                buildMethod = constructorResult.getClass().getMethod(BUILD_METHOD_NAME, (Class[]) null);
            } catch (NoSuchMethodException e) {
                throw new _ObjectBuilderSettingEvaluationException("The " + cl.getName()
                        + " builder class must have a public " + BUILD_METHOD_NAME + "() method", e);
            } catch (Exception e) {
                throw new _ObjectBuilderSettingEvaluationException("Failed to get the " + BUILD_METHOD_NAME
                        + "() method of the " + cl.getName() + " builder class", e);
            }
            
            try {
                return buildMethod.invoke(constructorResult, (Object[]) null);
            } catch (Exception e) {
                Throwable cause;
                if (e instanceof InvocationTargetException) {
                    cause = ((InvocationTargetException) e).getTargetException();
                } else {
                    cause = e;
                }
                throw new _ObjectBuilderSettingEvaluationException("Failed to call " + BUILD_METHOD_NAME
                        + "() method on " + cl.getName() + " instance", cause);
            }
        }

        private boolean hasNoParameters() {
            return positionalParamValues.isEmpty() && namedParamValues.isEmpty();
        }

        @Override
        protected boolean getAllowPositionalParameters() {
            return true;
        }
        
    }
    
    private class PropertyAssignmentsExpression extends ExpressionWithParameters {
        
        private final Object bean;
        
        public PropertyAssignmentsExpression(Object bean) {
            this.bean = bean;
        }

        @Override
        Object eval() throws _ObjectBuilderSettingEvaluationException {
            setJavaBeanProperties(bean, namedParamNames, namedParamValues);
            return bean;
        }

        @Override
        protected boolean getAllowPositionalParameters() {
            return false;
        }
        
    }
    
    private static class LegacyExceptionWrapperSettingEvaluationExpression
            extends _ObjectBuilderSettingEvaluationException {

        public LegacyExceptionWrapperSettingEvaluationExpression(Throwable cause) {
            super("Legacy operation failed", cause);
            if (!(
                    (cause instanceof ClassNotFoundException) 
                    || (cause instanceof InstantiationException)
                    || (cause instanceof IllegalAccessException)
                    )) {
                throw new IllegalArgumentException();
            }
        }

        public void rethrowLegacy() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
            Throwable cause = getCause();
            if (cause instanceof ClassNotFoundException) throw (ClassNotFoundException) cause;
            if (cause instanceof InstantiationException) throw (InstantiationException) cause;
            if (cause instanceof IllegalAccessException) throw (IllegalAccessException) cause;
            throw new BugException();
        }
        
    }
    
}
