/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.base.util.string;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import javax.el.PropertyNotFoundException;

import org.ofbiz.base.lang.IsEmpty;
import org.ofbiz.base.lang.SourceMonitored;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.ObjectType;
import org.ofbiz.base.util.ScriptUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilFormatOut;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.cache.Cache;
import org.ofbiz.base.util.cache.UtilCache;

/** Expands String values that contain Unified Expression Language (JSR 245)
 * syntax. This class also supports the execution of bsh scripts by using the
 * 'bsh:' prefix, and Groovy scripts by using the 'groovy:' prefix.
 * Further it is possible to control the output by specifying the suffix
 * '?currency(XXX)' to format the output according to the supplied locale
 * and specified (XXX) currency.<p>This class extends the UEL by allowing
 * nested expressions.</p>
 */
@SourceMonitored
@SuppressWarnings("serial")
public abstract class FlexibleStringExpander implements Serializable, IsEmpty {

    public static final String module = FlexibleStringExpander.class.getName();
    public static final String openBracket = "${";
    public static final String closeBracket = "}";
    protected static final Cache<Key, FlexibleStringExpander> exprCache = UtilCache.createUtilCache("flexibleStringExpander.ExpressionCache");
    protected static final FlexibleStringExpander nullExpr = new ConstSimpleElem(new char[0]);

    /**
     * Returns <code>true</code> if <code>fse</code> contains a <code>String</code> constant.
     * @param fse The <code>FlexibleStringExpander</code> to test
     * @return <code>true</code> if <code>fse</code> contains a <code>String</code> constant
     */
    public static boolean containsConstant(FlexibleStringExpander fse) {
        if (fse instanceof ConstSimpleElem || fse instanceof ConstOffsetElem) {
            return true;
        }
        if (fse instanceof Elements) {
            Elements fseElements = (Elements) fse;
            for (FlexibleStringExpander childElement : fseElements.childElems) {
                if (containsConstant(childElement)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns <code>true</code> if <code>fse</code> contains an expression.
     * @param fse The <code>FlexibleStringExpander</code> to test
     * @return <code>true</code> if <code>fse</code> contains an expression
     */
    public static boolean containsExpression(FlexibleStringExpander fse) {
        return !(fse instanceof ConstSimpleElem);
    }

    /**
     * Returns <code>true</code> if <code>fse</code> contains a script.
     * @param fse The <code>FlexibleStringExpander</code> to test
     * @return <code>true</code> if <code>fse</code> contains a script
     */
    public static boolean containsScript(FlexibleStringExpander fse) {
        if (fse instanceof ScriptElem) {
            return true;
        }
        if (fse instanceof Elements) {
            Elements fseElements = (Elements) fse;
            for (FlexibleStringExpander childElement : fseElements.childElems) {
                if (containsScript(childElement)) {
                    return true;
                }
            }
        }
        return false;
    }

    /** Evaluate an expression and return the result as a <code>String</code>.
     * Null expressions return <code>null</code>.
     * A null <code>context</code> argument will return the original expression.
     * <p>Note that the behavior of this method is not the same as using
     * <code>FlexibleStringExpander.getInstance(expression).expandString(context)</code>
     * because it returns <code>null</code> when given a null <code>expression</code>
     * argument, and
     * <code>FlexibleStringExpander.getInstance(expression).expandString(context)</code>
     * returns an empty <code>String</code>.</p>
     *
     * @param expression The original expression
     * @param context The evaluation context
     * @return The original expression's evaluation result as a <code>String</code>
     */
    public static String expandString(String expression, Map<String, ? extends Object> context) {
        return expandString(expression, context, null, null);
    }

    /** Evaluate an expression and return the result as a <code>String</code>.
     * Null expressions return <code>null</code>.
     * A null <code>context</code> argument will return the original expression.
     * <p>Note that the behavior of this method is not the same as using
     * <code>FlexibleStringExpander.getInstance(expression).expandString(context, locale)</code>
     * because it returns <code>null</code> when given a null <code>expression</code>
     * argument, and
     * <code>FlexibleStringExpander.getInstance(expression).expandString(context, locale)</code>
     * returns an empty <code>String</code>.</p>
     *
     * @param expression The original expression
     * @param context The evaluation context
     * @param locale The locale to be used for localization
     * @return The original expression's evaluation result as a <code>String</code>
     */
    public static String expandString(String expression, Map<String, ? extends Object> context, Locale locale) {
        return expandString(expression, context, null, locale);
    }

    /** Evaluate an expression and return the result as a <code>String</code>.
     * Null expressions return <code>null</code>.
     * A null <code>context</code> argument will return the original expression.
     * <p>Note that the behavior of this method is not the same as using
     * <code>FlexibleStringExpander.getInstance(expression).expandString(context, timeZone locale)</code>
     * because it returns <code>null</code> when given a null <code>expression</code>
     * argument, and
     * <code>FlexibleStringExpander.getInstance(expression).expandString(context, timeZone, locale)</code>
     * returns an empty <code>String</code>.</p>
     *
     * @param expression The original expression
     * @param context The evaluation context
     * @param timeZone The time zone to be used for localization
     * @param locale The locale to be used for localization
     * @return The original expression's evaluation result as a <code>String</code>
     */
    public static String expandString(String expression, Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
        if (expression == null) {
            return "";
        }
        if (context == null || !expression.contains(openBracket)) {
            return expression;
        }
        FlexibleStringExpander fse = FlexibleStringExpander.getInstance(expression);
        return fse.expandString(context, timeZone, locale);
    }

    /** Returns a <code>FlexibleStringExpander</code> object. <p>A null or
     * empty argument will return a <code>FlexibleStringExpander</code>
     * object that represents an empty expression. That object is a shared
     * singleton, so there is no memory or performance penalty in using it.</p>
     * <p>If the method is passed a <code>String</code> argument that doesn't
     * contain an expression, the <code>FlexibleStringExpander</code> object
     * that is returned does not perform any evaluations on the original
     * <code>String</code> - any methods that return a <code>String</code>
     * will return the original <code>String</code>. The object returned by
     * this method is very compact - taking less memory than the original
     * <code>String</code>.</p>
     *
     * @param expression The original expression
     * @return A <code>FlexibleStringExpander</code> instance
     */
    public static FlexibleStringExpander getInstance(String expression) {
        return getInstance(expression, true);
    }

    /* Returns a <code>FlexibleStringExpander</code> object. <p>A null or
     * empty argument will return a <code>FlexibleStringExpander</code>
     * object that represents an empty expression. That object is a shared
     * singleton, so there is no memory or performance penalty in using it.</p>
     * <p>If the method is passed a <code>String</code> argument that doesn't
     * contain an expression, the <code>FlexibleStringExpander</code> object
     * that is returned does not perform any evaluations on the original
     * <code>String</code> - any methods that return a <code>String</code>
     * will return the original <code>String</code>. The object returned by
     * this method is very compact - taking less memory than the original
     * <code>String</code>.</p>
     *
     * @param expression The original expression
     * @param useCache whether to store things into a global cache
     * @return A <code>FlexibleStringExpander</code> instance
     */
    public static FlexibleStringExpander getInstance(String expression, boolean useCache) {
        if (UtilValidate.isEmpty(expression)) {
            return nullExpr;
        }
        return getInstance(expression, expression.toCharArray(), 0, expression.length(), useCache);
    }

    private static FlexibleStringExpander getInstance(String expression, char[] chars, int offset, int length, boolean useCache) {
        if (length == 0) {
            return nullExpr;
        }
        if (!useCache) {
            return parse(chars, offset, length);
        }
        // Remove the next nine lines to cache all expressions
        if (!expression.contains(openBracket)) {
            if (chars.length == length) {
                return new ConstSimpleElem(chars);
            } else {
                return new ConstOffsetElem(chars, offset, length);
            }
        }
        Key key = chars.length == length ? new SimpleKey(chars) : new OffsetKey(chars, offset, length);
        FlexibleStringExpander fse = exprCache.get(key);
        if (fse == null) {
            exprCache.put(key, parse(chars, offset, length));
            fse = exprCache.get(key);
        }
        return fse;
    }

    private static abstract class Key {
        @Override
        public final boolean equals(Object o) {
            // No class test here, nor null, as this class is only used
            // internally
            return toString().equals(o.toString());
        }

        @Override
        public final int hashCode() {
            return toString().hashCode();
        }
    }

    private static final class SimpleKey extends Key {
        private final char[] chars;

        protected SimpleKey(char[] chars) {
            this.chars = chars;
        }

        @Override
        public String toString() {
            return new String(chars);
        }
    }

    private static final class OffsetKey extends Key {
        private final char[] chars;
        private final int offset;
        private final int length;

        protected OffsetKey(char[] chars, int offset, int length) {
            this.chars = chars;
            this.offset = offset;
            this.length = length;
        }

        @Override
        public String toString() {
            return new String(chars, offset, length);
        }
    }

    private static FlexibleStringExpander parse(char[] chars, int offset, int length) {
        FlexibleStringExpander[] strElems = getStrElems(chars, offset, length);
        if (strElems.length == 1) {
            return strElems[0];
        } else {
            return new Elements(chars, offset, length, strElems);
        }
    }

    protected static FlexibleStringExpander[] getStrElems(char[] chars, int offset, int length) {
        String expression = new String(chars, 0, length + offset);
        int start = expression.indexOf(openBracket, offset);
        if (start == -1) {
            return new FlexibleStringExpander[] { new ConstOffsetElem(chars, offset, length) };
        }
        int origLen = length;
        ArrayList<FlexibleStringExpander> strElems = new ArrayList<FlexibleStringExpander>();
        int currentInd = offset;
        int end = -1;
        while (start != -1) {
            end = expression.indexOf(closeBracket, start);
            if (end == -1) {
                Debug.logWarning("Found a ${ without a closing } (curly-brace) in the String: " + expression, module);
                break;
            }
            // Check for escaped expression
            boolean escapedExpression = (start - 1 >= 0 && expression.charAt(start - 1) == '\\');
            if (start > currentInd) {
                // append everything from the current index to the start of the expression
                strElems.add(new ConstOffsetElem(chars, currentInd, (escapedExpression ? start -1 : start) - currentInd));
            }
            if (expression.indexOf("bsh:", start + 2) == start + 2 && !escapedExpression) {
                // checks to see if this starts with a "bsh:", if so treat the rest of the expression as a bsh scriptlet
                strElems.add(new ScriptElem(chars, start, Math.min(end + 1, start + length) - start, start + 6, end - start - 6));
            } else if (expression.indexOf("groovy:", start + 2) == start + 2 && !escapedExpression) {
                // checks to see if this starts with a "groovy:", if so treat the rest of the expression as a groovy scriptlet
                strElems.add(new ScriptElem(chars, start, Math.min(end + 1, start + length) - start, start + 9, end - start - 9));
            } else {
                // Scan for matching closing bracket
                int ptr = expression.indexOf("{", start + 2);
                while (ptr != -1 && end != -1 && ptr < end) {
                    end = expression.indexOf(closeBracket, end + 1);
                    ptr = expression.indexOf("{", ptr + 1);
                }
                if (end == -1) {
                    end = origLen;
                }
                // Evaluation sequence is important - do not change it
                if (escapedExpression) {
                    strElems.add(new ConstOffsetElem(chars, start, end + 1 - start));
                } else {
                    String subExpression = expression.substring(start + 2, end);
                    int currencyPos = subExpression.indexOf("?currency(");
                    int closeParen = currencyPos > 0 ? subExpression.indexOf(")", currencyPos + 10) : -1;
                    if (closeParen != -1) {
                        strElems.add(new CurrElem(chars, start, Math.min(end + 1, start + length) - start, start + 2, end - start - 1));
                    } else if (subExpression.contains(openBracket)) {
                        strElems.add(new NestedVarElem(chars, start, Math.min(end + 1, start + length) - start, start + 2, Math.min(end - 2, start + length) - start));
                    } else {
                        strElems.add(new VarElem(chars, start, Math.min(end + 1, start + length) - start, start + 2, Math.min(end - 2, start + length) - start));
                    }
                }
            }
            // reset the current index to after the expression, and the start to the beginning of the next expression
            currentInd = end + 1;
            if (currentInd > origLen + offset) {
                currentInd = origLen + offset;
            }
            start = expression.indexOf(openBracket, currentInd);
        }
        // append the rest of the original string, ie after the last expression
        if (currentInd < origLen + offset) {
            strElems.add(new ConstOffsetElem(chars, currentInd, offset + length - currentInd));
        }
        return strElems.toArray(new FlexibleStringExpander[strElems.size()]);
    }

    // Note: a character array is used instead of a String to keep the memory footprint small.
    protected final char[] chars;
    protected int hint = 20;

    protected FlexibleStringExpander(char[] chars) {
        this.chars = chars;
    }

    protected abstract Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale);

    private static Locale getLocale(Locale locale, Map<String, ? extends Object> context) {
        if (locale == null) {
            locale = (Locale) context.get("locale");
            if (locale == null && context.containsKey("autoUserLogin")) {
                Map<String, Object> autoUserLogin = UtilGenerics.cast(context.get("autoUserLogin"));
                locale = UtilMisc.ensureLocale(autoUserLogin.get("lastLocale"));
            }
            if (locale == null) {
                locale = Locale.getDefault();
            }
        }
        return locale;
    }

    private static TimeZone getTimeZone(TimeZone timeZone, Map<String, ? extends Object> context) {
        if (timeZone == null) {
            timeZone = (TimeZone) context.get("timeZone");
            if (timeZone == null && context.containsKey("autoUserLogin")) {
                Map<String, String> autoUserLogin = UtilGenerics.cast(context.get("autoUserLogin"));
                timeZone = UtilDateTime.toTimeZone(autoUserLogin.get("lastTimeZone"));
            }
            if (timeZone == null) {
                timeZone = TimeZone.getDefault();
            }
        }
        return timeZone;
    }

    /** Evaluate this object's expression and return the result as a <code>String</code>.
     * Null or empty expressions return an empty <code>String</code>.
     * A <code>null context</code> argument will return the original expression.
     *
     * @param context The evaluation context
     * @return This object's expression result as a <code>String</code>
     */
    public String expandString(Map<String, ? extends Object> context) {
        return this.expandString(context, null, null);
    }

    /** Evaluate this object's expression and return the result as a <code>String</code>.
     * Null or empty expressions return an empty <code>String</code>.
     * A <code>null context</code> argument will return the original expression.
     *
     * @param context The evaluation context
     * @param locale The locale to be used for localization
     * @return This object's expression result as a <code>String</code>
     */
    public String expandString(Map<String, ? extends Object> context, Locale locale) {
        return this.expandString(context, null, locale);
    }

    /** Evaluate this object's expression and return the result as a <code>String</code>.
     * Null or empty expressions return an empty <code>String</code>.
     * A <code>null context</code> argument will return the original expression.
     *
     * @param context The evaluation context
     * @param timeZone The time zone to be used for localization
     * @param locale The locale to be used for localization
     * @return This object's expression result as a <code>String</code>
     */
    public String expandString(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
        if (context == null) {
            return this.toString();
        }
        timeZone = getTimeZone(timeZone, context);
        locale = getLocale(locale, context);
        Object obj = get(context, timeZone, locale);
        StringBuilder buffer = new StringBuilder(this.hint);
        try {
            if (obj != null) {
                if (obj instanceof String) {
                    buffer.append(obj);
                } else {
                    buffer.append(ObjectType.simpleTypeConvert(obj, "String", null, timeZone, locale, true));
                }
            }
        } catch (Exception e) {
            buffer.append(obj);
        }
        if (buffer.length() > this.hint) {
            this.hint = buffer.length();
        }
        return buffer.toString();
    }

    /** Evaluate this object's expression and return the result as an <code>Object</code>.
     * Null or empty expressions return an empty <code>String</code>.
     * A <code>null context</code> argument will return the original expression.
     *
     * @param context The evaluation context
     * @return This object's expression result as a <code>String</code>
     */
    public Object expand(Map<String, ? extends Object> context) {
        return this.expand(context, null, null);
    }

    /** Evaluate this object's expression and return the result as an <code>Object</code>.
     * Null or empty expressions return an empty <code>String</code>.
     * A <code>null context</code> argument will return the original expression.
     *
     * @param context The evaluation context
     * @param locale The locale to be used for localization
     * @return This object's expression result as a <code>String</code>
     */
    public Object expand(Map<String, ? extends Object> context, Locale locale) {
        return this.expand(context, null, locale);
    }

    /** Evaluate this object's expression and return the result as an <code>Object</code>.
     * Null or empty expressions return an empty <code>String</code>.
     * A <code>null context</code> argument will return the original expression.
     *
     * @param context The evaluation context
     * @param timeZone The time zone to be used for localization
     * @param locale The locale to be used for localization
     * @return This object's expression result as a <code>String</code>
     */
    public Object expand(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
        if (context == null) {
            return null;
        }
        return get(context, getTimeZone(timeZone, context), getLocale(locale, context));
    }

    /** Returns a copy of the original expression.
     *
     * @return The original expression
     */
    public abstract String getOriginal();

    /** Returns <code>true</code> if the original expression is empty
     * or <code>null</code>.
     *
     * @return <code>true</code> if the original expression is empty
     * or <code>null</code>
     */
    public abstract boolean isEmpty();

    /** Returns a copy of the original expression.
     *
     * @return The original expression
     */
    @Override
    public String toString() {
        return this.getOriginal();
    }

    protected static abstract class ArrayOffsetString extends FlexibleStringExpander {
        protected final int offset;
        protected final int length;

        protected ArrayOffsetString(char[] chars, int offset, int length) {
            super(chars);
            this.offset = offset;
            this.length = length;
        }
        @Override
        public boolean isEmpty() {
            // This is always false; the complex child classes can't be
            // empty, as they contain at least ${; constant elements
            // with a length of 0 will never be created.
            return false;
        }
        @Override
        public String getOriginal() {
            return new String(this.chars, this.offset, this.length);
        }
    }

    /** An object that represents a <code>String</code> constant portion of an expression. */
    protected static class ConstSimpleElem extends FlexibleStringExpander {
        protected ConstSimpleElem(char[] chars) {
            super(chars);
        }

        @Override
        public boolean isEmpty() {
            return this.chars.length == 0;
        }

        @Override
        public String getOriginal() {
            return new String(this.chars);
        }

        @Override
        public String expandString(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            return getOriginal();
        }

        @Override
        protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            return isEmpty() ? null : getOriginal();
        }
    }

    /** An object that represents a <code>String</code> constant portion of an expression. */
    protected static class ConstOffsetElem extends ArrayOffsetString {
        protected ConstOffsetElem(char[] chars, int offset, int length) {
            super(chars, offset, length);
        }

        @Override
        protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            return getOriginal();
        }

        @Override
        public String expandString(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            return new String(this.chars, this.offset, this.length);
        }
    }

    /** An object that represents a currency portion of an expression. */
    protected static class CurrElem extends ArrayOffsetString {
        protected final char[] valueStr;
        protected final FlexibleStringExpander codeExpr;

        protected CurrElem(char[] chars, int offset, int length, int parseStart, int parseLength) {
            super(chars, offset, length);
            String parse = new String(chars, parseStart, parseLength);
            int currencyPos = parse.indexOf("?currency(");
            int closeParen = parse.indexOf(")", currencyPos + 10);
            this.codeExpr = FlexibleStringExpander.getInstance(parse, chars, parseStart + currencyPos + 10, closeParen - currencyPos - 10, true);
            this.valueStr = openBracket.concat(parse.substring(0, currencyPos)).concat(closeBracket).toCharArray();
        }

        @Override
        protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            try {
                Object obj = UelUtil.evaluate(context, new String(this.valueStr));
                if (obj != null) {
                    String currencyCode = this.codeExpr.expandString(context, timeZone, locale);
                    return UtilFormatOut.formatCurrency(new BigDecimal(obj.toString()), currencyCode, locale);
                }
            } catch (PropertyNotFoundException e) {
                if (Debug.verboseOn()) {
                    Debug.logVerbose("Error evaluating expression: " + e, module);
                }
            } catch (Exception e) {
                Debug.logError("Error evaluating expression: " + e, module);
            }
            return null;
        }
    }

    /** A container object that contains expression fragments. */
    protected static class Elements extends ArrayOffsetString {
        protected final FlexibleStringExpander[] childElems;

        protected Elements(char[] chars, int offset, int length, FlexibleStringExpander[] childElems) {
            super(chars, offset, length);
            this.childElems = childElems;
        }

        @Override
        protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            StringBuilder buffer = new StringBuilder();
            for (FlexibleStringExpander child : this.childElems) {
                buffer.append(child.expandString(context, timeZone, locale));
            }
            return buffer.toString();
        }
    }

    /** An object that represents a <code>${[groovy|bsh]:}</code> expression. */
    protected static class ScriptElem extends ArrayOffsetString {
        private final String language;
        private final int parseStart;
        private final int parseLength;
        private final String script;
        protected final Class<?> parsedScript;

        protected ScriptElem(char[] chars, int offset, int length, int parseStart, int parseLength) {
            super(chars, offset, length);
            this.language = new String(this.chars, offset + 2, parseStart - offset - 3);
            this.parseStart = parseStart;
            this.parseLength = parseLength;
            this.script = new String(this.chars, this.parseStart, this.parseLength);
            this.parsedScript = ScriptUtil.parseScript(this.language, this.script);
        }

        @Override
        protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            try {
                Map <String, Object> contextCopy = new HashMap<String, Object>(context);
                Object obj = ScriptUtil.evaluate(this.language, this.script, this.parsedScript, contextCopy);
                if (obj != null) {
                    return obj;
                } else {
                    if (Debug.verboseOn()) {
                        Debug.logVerbose("Scriptlet evaluated to null [" + this + "].", module);
                    }
                }
            } catch (Exception e) {
                Debug.logWarning(e, "Error evaluating scriptlet [" + this + "]; error was: " + e, module);
            }
            return null;
        }
    }

    /** An object that represents a nested expression. */
    protected static class NestedVarElem extends ArrayOffsetString {
        protected final FlexibleStringExpander[] childElems;

        protected NestedVarElem(char[] chars, int offset, int length, int parseStart, int parseLength) {
            super(chars, offset, length);
            this.childElems = getStrElems(chars, parseStart, parseLength);
            if (length > this.hint) {
                this.hint = length;
            }
        }

        @Override
        protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            StringBuilder expr = new StringBuilder(this.hint);
            for (FlexibleStringExpander child : this.childElems) {
                expr.append(child.expandString(context, timeZone, locale));
            }
            if (expr.length() == 0) {
                return "";
            }
            try {
                return UelUtil.evaluate(context, openBracket.concat(expr.toString()).concat(closeBracket));
            } catch (PropertyNotFoundException e) {
                if (Debug.verboseOn()) {
                    Debug.logVerbose("Error evaluating expression: " + e, module);
                }
            } catch (Exception e) {
                Debug.logError("Error evaluating expression: " + e, module);
            }
            return "";
        }
    }

    /** An object that represents a simple, non-nested expression. */
    protected static class VarElem extends ArrayOffsetString {
        protected final char[] bracketedOriginal;

        protected VarElem(char[] chars, int offset, int length, int parseStart, int parseLength) {
            super(chars, offset, length);
            this.bracketedOriginal = openBracket.concat(UelUtil.prepareExpression(new String(chars, parseStart, parseLength))).concat(closeBracket).toCharArray();
        }

        @Override
        protected Object get(Map<String, ? extends Object> context, TimeZone timeZone, Locale locale) {
            Object obj = null;
            try {
                obj = UelUtil.evaluate(context, new String(this.bracketedOriginal));
            } catch (PropertyNotFoundException e) {
                if (Debug.verboseOn()) {
                    Debug.logVerbose("Error evaluating expression " + this + ": " + e, module);
                }
            } catch (Exception e) {
                Debug.logError("Error evaluating expression " + this + ": " + e, module);
            }
            return obj;
        }
    }
}
