freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [23/54] [partial] incubator-freemarker git commit: Unifying the o.a.f.core and o.a.f.core.ast
Date Thu, 23 Feb 2017 21:35:50 GMT
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormat.java b/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormat.java
deleted file mode 100644
index ed94371..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormat.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.util.Date;
-import java.util.TimeZone;
-
-import org.apache.freemarker.core.model.TemplateDateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.util._DateUtil;
-import org.apache.freemarker.core.util._StringUtil;
-import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter;
-import org.apache.freemarker.core.util._DateUtil.DateParseException;
-import org.apache.freemarker.core.util._DateUtil.DateToISO8601CalendarFactory;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
-abstract class ISOLikeTemplateDateFormat  extends TemplateDateFormat {
-    
-    private static final String XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE
-            = "Less than seconds accuracy isn't allowed by the XML Schema format";
-    private final ISOLikeTemplateDateFormatFactory factory;
-    private final Environment env;
-    protected final int dateType;
-    protected final boolean zonelessInput;
-    protected final TimeZone timeZone;
-    protected final Boolean forceUTC;
-    protected final Boolean showZoneOffset;
-    protected final int accuracy;
-
-    /**
-     * @param formatString The value of the ..._format setting, like "iso nz".
-     * @param parsingStart The index of the char in the {@code settingValue} that directly after the prefix that has
-     *     indicated the exact formatter class (like "iso" or "xs") 
-     */
-    public ISOLikeTemplateDateFormat(
-            final String formatString, int parsingStart,
-            int dateType, boolean zonelessInput,
-            TimeZone timeZone,
-            ISOLikeTemplateDateFormatFactory factory, Environment env)
-            throws InvalidFormatParametersException, UnknownDateTypeFormattingUnsupportedException {
-        this.factory = factory;
-        this.env = env;
-        if (dateType == TemplateDateModel.UNKNOWN) {
-            throw new UnknownDateTypeFormattingUnsupportedException();
-        }
-        
-        this.dateType = dateType;
-        this.zonelessInput = zonelessInput;
-        
-        final int ln = formatString.length();
-        boolean afterSeparator = false;
-        int i = parsingStart;
-        int accuracy = _DateUtil.ACCURACY_MILLISECONDS;
-        Boolean showZoneOffset = null;
-        Boolean forceUTC = Boolean.FALSE;
-        while (i < ln) {
-            final char c = formatString.charAt(i++);
-            if (c == '_' || c == ' ') {
-                afterSeparator = true;
-            } else {
-                if (!afterSeparator) {
-                    throw new InvalidFormatParametersException(
-                            "Missing space or \"_\" before \"" + c + "\" (at char pos. " + i + ").");
-                }
-                
-                switch (c) {
-                case 'h':
-                case 'm':
-                case 's':
-                    if (accuracy != _DateUtil.ACCURACY_MILLISECONDS) {
-                        throw new InvalidFormatParametersException(
-                                "Character \"" + c + "\" is unexpected as accuracy was already specified earlier "
-                                + "(at char pos. " + i + ").");
-                    }
-                    switch (c) {
-                    case 'h':
-                        if (isXSMode()) {
-                            throw new InvalidFormatParametersException(
-                                    XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE);
-                        }
-                        accuracy = _DateUtil.ACCURACY_HOURS;
-                        break;
-                    case 'm':
-                        if (i < ln && formatString.charAt(i) == 's') {
-                            i++;
-                            accuracy = _DateUtil.ACCURACY_MILLISECONDS_FORCED;
-                        } else {
-                            if (isXSMode()) {
-                                throw new InvalidFormatParametersException(
-                                        XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE);
-                            }
-                            accuracy = _DateUtil.ACCURACY_MINUTES;
-                        }
-                        break;
-                    case 's':
-                        accuracy = _DateUtil.ACCURACY_SECONDS;
-                        break;
-                    }
-                    break;
-                case 'f':
-                    if (i < ln && formatString.charAt(i) == 'u') {
-                        checkForceUTCNotSet(forceUTC);
-                        i++;
-                        forceUTC = Boolean.TRUE;
-                        break;
-                    }
-                    // Falls through
-                case 'n':
-                    if (showZoneOffset != null) {
-                        throw new InvalidFormatParametersException(
-                                "Character \"" + c + "\" is unexpected as zone offset visibility was already "
-                                + "specified earlier. (at char pos. " + i + ").");
-                    }
-                    switch (c) {
-                    case 'n':
-                        if (i < ln && formatString.charAt(i) == 'z') {
-                            i++;
-                            showZoneOffset = Boolean.FALSE;
-                        } else {
-                            throw new InvalidFormatParametersException(
-                                    "\"n\" must be followed by \"z\" (at char pos. " + i + ").");
-                        }
-                        break;
-                    case 'f':
-                        if (i < ln && formatString.charAt(i) == 'z') {
-                            i++;
-                            showZoneOffset = Boolean.TRUE;
-                        } else {
-                            throw new InvalidFormatParametersException(
-                                    "\"f\" must be followed by \"z\" (at char pos. " + i + ").");
-                        }
-                        break;
-                    }
-                    break;
-                case 'u':
-                    checkForceUTCNotSet(forceUTC);
-                    forceUTC = null;  // means UTC will be used except for zonelessInput
-                    break;
-                default:
-                    throw new InvalidFormatParametersException(
-                            "Unexpected character, " + _StringUtil.jQuote(String.valueOf(c))
-                            + ". Expected the beginning of one of: h, m, s, ms, nz, fz, u"
-                            + " (at char pos. " + i + ").");
-                } // switch
-                afterSeparator = false;
-            } // else
-        } // while
-        
-        this.accuracy = accuracy;
-        this.showZoneOffset = showZoneOffset;
-        this.forceUTC = forceUTC;
-        this.timeZone = timeZone;
-    }
-
-    private void checkForceUTCNotSet(Boolean fourceUTC) throws InvalidFormatParametersException {
-        if (fourceUTC != Boolean.FALSE) {
-            throw new InvalidFormatParametersException(
-                    "The UTC usage option was already set earlier.");
-        }
-    }
-    
-    @Override
-    public final String formatToPlainText(TemplateDateModel dateModel) throws TemplateModelException {
-        final Date date = TemplateFormatUtil.getNonNullDate(dateModel);
-        return format(
-                date,
-                dateType != TemplateDateModel.TIME,
-                dateType != TemplateDateModel.DATE,
-                showZoneOffset == null
-                        ? !zonelessInput
-                        : showZoneOffset.booleanValue(),
-                accuracy,
-                (forceUTC == null ? !zonelessInput : forceUTC.booleanValue()) ? _DateUtil.UTC : timeZone,
-                factory.getISOBuiltInCalendar(env));
-    }
-    
-    protected abstract String format(Date date,
-            boolean datePart, boolean timePart, boolean offsetPart,
-            int accuracy,
-            TimeZone timeZone,
-            DateToISO8601CalendarFactory calendarFactory);
-
-    @Override
-    @SuppressFBWarnings(value = "RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN",
-            justification = "Known to use the singleton Boolean-s only")
-    public final Date parse(String s, int dateType) throws UnparsableValueException {
-        CalendarFieldsToDateConverter calToDateConverter = factory.getCalendarFieldsToDateCalculator(env);
-        TimeZone tz = forceUTC != Boolean.FALSE ? _DateUtil.UTC : timeZone;
-        try {
-            if (dateType == TemplateDateModel.DATE) {
-                return parseDate(s, tz, calToDateConverter);
-            } else if (dateType == TemplateDateModel.TIME) {
-                return parseTime(s, tz, calToDateConverter);
-            } else if (dateType == TemplateDateModel.DATETIME) {
-                return parseDateTime(s, tz, calToDateConverter);
-            } else {
-                throw new BugException("Unexpected date type: " + dateType);
-            }
-        } catch (DateParseException e) {
-            throw new UnparsableValueException(e.getMessage(), e);
-        }
-    }
-    
-    protected abstract Date parseDate(
-            String s, TimeZone tz,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException;
-    
-    protected abstract Date parseTime(
-            String s, TimeZone tz,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException;
-    
-    protected abstract Date parseDateTime(
-            String s, TimeZone tz,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException;
-
-    @Override
-    public final String getDescription() {
-        switch (dateType) {
-            case TemplateDateModel.DATE: return getDateDescription();
-            case TemplateDateModel.TIME: return getTimeDescription();
-            case TemplateDateModel.DATETIME: return getDateTimeDescription();
-            default: return "<error: wrong format dateType>";
-        }
-    }
-    
-    protected abstract String getDateDescription();
-    protected abstract String getTimeDescription();
-    protected abstract String getDateTimeDescription();
-    
-    @Override
-    public final boolean isLocaleBound() {
-        return false;
-    }
-    
-    @Override
-    public boolean isTimeZoneBound() {
-        return true;
-    }
-
-    protected abstract boolean isXSMode();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormatFactory.java b/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormatFactory.java
deleted file mode 100644
index e51f2d0..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/ISOLikeTemplateDateFormatFactory.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter;
-import org.apache.freemarker.core.util._DateUtil.DateToISO8601CalendarFactory;
-import org.apache.freemarker.core.util._DateUtil.TrivialCalendarFieldsToDateConverter;
-import org.apache.freemarker.core.util._DateUtil.TrivialDateToISO8601CalendarFactory;
-
-abstract class ISOLikeTemplateDateFormatFactory extends TemplateDateFormatFactory {
-    
-    private static final Object DATE_TO_CAL_CONVERTER_KEY = new Object();
-    private static final Object CAL_TO_DATE_CONVERTER_KEY = new Object();
-    
-    protected ISOLikeTemplateDateFormatFactory() { }
-
-    public DateToISO8601CalendarFactory getISOBuiltInCalendar(Environment env) {
-        DateToISO8601CalendarFactory r = (DateToISO8601CalendarFactory) env.getCustomState(DATE_TO_CAL_CONVERTER_KEY);
-        if (r == null) {
-            r = new TrivialDateToISO8601CalendarFactory();
-            env.setCustomState(DATE_TO_CAL_CONVERTER_KEY, r);
-        }
-        return r;
-    }
-
-    public CalendarFieldsToDateConverter getCalendarFieldsToDateCalculator(Environment env) {
-        CalendarFieldsToDateConverter r = (CalendarFieldsToDateConverter) env.getCustomState(CAL_TO_DATE_CONVERTER_KEY);
-        if (r == null) {
-            r = new TrivialCalendarFieldsToDateConverter();
-            env.setCustomState(CAL_TO_DATE_CONVERTER_KEY, r);
-        }
-        return r;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormat.java b/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormat.java
deleted file mode 100644
index 7bff342..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormat.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.util.Date;
-import java.util.TimeZone;
-
-import org.apache.freemarker.core.util._DateUtil;
-import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter;
-import org.apache.freemarker.core.util._DateUtil.DateParseException;
-import org.apache.freemarker.core.util._DateUtil.DateToISO8601CalendarFactory;
-
-final class ISOTemplateDateFormat extends ISOLikeTemplateDateFormat {
-
-    ISOTemplateDateFormat(
-            String settingValue, int parsingStart,
-            int dateType, boolean zonelessInput,
-            TimeZone timeZone,
-            ISOLikeTemplateDateFormatFactory factory,
-            Environment env)
-            throws InvalidFormatParametersException, UnknownDateTypeFormattingUnsupportedException {
-        super(settingValue, parsingStart, dateType, zonelessInput, timeZone, factory, env);
-    }
-
-    @Override
-    protected String format(Date date, boolean datePart, boolean timePart, boolean offsetPart, int accuracy,
-            TimeZone timeZone, DateToISO8601CalendarFactory calendarFactory) {
-        return _DateUtil.dateToISO8601String(
-                date, datePart, timePart, timePart && offsetPart, accuracy, timeZone, calendarFactory);
-    }
-
-    @Override
-    protected Date parseDate(String s, TimeZone tz, CalendarFieldsToDateConverter calToDateConverter)
-            throws DateParseException {
-        return _DateUtil.parseISO8601Date(s, tz, calToDateConverter);
-    }
-
-    @Override
-    protected Date parseTime(String s, TimeZone tz, CalendarFieldsToDateConverter calToDateConverter)
-            throws DateParseException {
-        return _DateUtil.parseISO8601Time(s, tz, calToDateConverter);
-    }
-
-    @Override
-    protected Date parseDateTime(String s, TimeZone tz,
-            CalendarFieldsToDateConverter calToDateConverter) throws DateParseException {
-        return _DateUtil.parseISO8601DateTime(s, tz, calToDateConverter);
-    }
-    
-    @Override
-    protected String getDateDescription() {
-        return "ISO 8601 (subset) date";
-    }
-
-    @Override
-    protected String getTimeDescription() {
-        return "ISO 8601 (subset) time";
-    }
-
-    @Override
-    protected String getDateTimeDescription() {
-        return "ISO 8601 (subset) date-time";
-    }
-
-    @Override
-    protected boolean isXSMode() {
-        return false;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormatFactory.java b/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormatFactory.java
deleted file mode 100644
index 4f5d484..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/ISOTemplateDateFormatFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.util.Locale;
-import java.util.TimeZone;
-
-class ISOTemplateDateFormatFactory extends ISOLikeTemplateDateFormatFactory {
-    
-    static final ISOTemplateDateFormatFactory INSTANCE = new ISOTemplateDateFormatFactory();
-
-    private ISOTemplateDateFormatFactory() {
-        // Not meant to be instantiated
-    }
-
-    @Override
-    public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput,
-            Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException {
-        // We don't cache these as creating them is cheap (only 10% speedup of ${d?string.xs} with caching)
-        return new ISOTemplateDateFormat(
-                params, 3,
-                dateType, zonelessInput,
-                timeZone, this, env);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Identifier.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/Identifier.java b/src/main/java/org/apache/freemarker/core/ast/Identifier.java
deleted file mode 100644
index 3ac82d5..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/Identifier.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.util._StringUtil;
-
-/**
- * A reference to a top-level variable
- */
-final class Identifier extends Expression {
-
-    private final String name;
-
-    Identifier(String name) {
-        this.name = name;
-    }
-
-    @Override
-    TemplateModel _eval(Environment env) throws TemplateException {
-        try {
-            return env.getVariable(name);
-        } catch (NullPointerException e) {
-            if (env == null) {
-                throw new _MiscTemplateException(
-                        "Variables are not available (certainly you are in a parse-time executed directive). "
-                        + "The name of the variable you tried to read: ", name);
-            } else {
-                throw e;
-            }
-        }
-    }
-
-    @Override
-    public String getCanonicalForm() {
-        return _StringUtil.toFTLTopLevelIdentifierReference(name);
-    }
-    
-    /**
-     * The name of the identifier without any escaping or other syntactical distortions. 
-     */
-    String getName() {
-        return name;
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return getCanonicalForm();
-    }
-
-    @Override
-    boolean isLiteral() {
-        return false;
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 0;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        throw new IndexOutOfBoundsException();
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        throw new IndexOutOfBoundsException();
-    }
-
-    @Override
-    protected Expression deepCloneWithIdentifierReplaced_inner(
-            String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) {
-        if (name.equals(replacedIdentifier)) {
-            if (replacementState.replacementAlreadyInUse) {
-                Expression clone = replacement.deepCloneWithIdentifierReplaced(null, null, replacementState);
-                clone.copyLocationFrom(replacement);
-                return clone;
-            } else {
-                replacementState.replacementAlreadyInUse = true;
-                return replacement;
-            }
-        } else {
-            return new Identifier(name);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/IfBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/IfBlock.java b/src/main/java/org/apache/freemarker/core/ast/IfBlock.java
deleted file mode 100644
index 4d7ef5c..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/IfBlock.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.io.IOException;
-
-import org.apache.freemarker.core.TemplateException;
-
-/**
- * Container for a group of related #if, #elseif and #else elements.
- * Each such block is a nested {@link ConditionalBlock}. Note that if an #if has no #else of #elseif,
- * {@link ConditionalBlock} doesn't need this parent element. 
- */
-final class IfBlock extends TemplateElement {
-
-    IfBlock(ConditionalBlock block) {
-        setChildBufferCapacity(1);
-        addBlock(block);
-    }
-
-    void addBlock(ConditionalBlock block) {
-        addChild(block);
-    }
-
-    @Override
-    TemplateElement[] accept(Environment env) throws TemplateException, IOException {
-        int ln  = getChildCount();
-        for (int i = 0; i < ln; i++) {
-            ConditionalBlock cblock = (ConditionalBlock) getChild(i);
-            Expression condition = cblock.condition;
-            env.replaceElementStackTop(cblock);
-            if (condition == null || condition.evalToBoolean(env)) {
-                return cblock.getChildBuffer();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    TemplateElement postParseCleanup(boolean stripWhitespace)
-        throws ParseException {
-        if (getChildCount() == 1) {
-            ConditionalBlock cblock = (ConditionalBlock) getChild(0);
-            cblock.setLocation(getTemplate(), cblock, this);
-            return cblock.postParseCleanup(stripWhitespace);
-        } else {
-            return super.postParseCleanup(stripWhitespace);
-        }
-    }
-    
-    @Override
-    protected String dump(boolean canonical) {
-        if (canonical) {
-            StringBuilder buf = new StringBuilder();
-            int ln = getChildCount();
-            for (int i = 0; i < ln; i++) {
-                ConditionalBlock cblock = (ConditionalBlock) getChild(i);
-                buf.append(cblock.dump(canonical));
-            }
-            buf.append("</#if>");
-            return buf.toString();
-        } else {
-            return getNodeTypeSymbol();
-        }
-    }
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return "#if-#elseif-#else-container";
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 0;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        throw new IndexOutOfBoundsException();
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        throw new IndexOutOfBoundsException();
-    }
-
-    @Override
-    boolean isNestedBlockRepeater() {
-        return false;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Include.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/Include.java b/src/main/java/org/apache/freemarker/core/ast/Include.java
deleted file mode 100644
index 8e9d78b..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/Include.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.io.IOException;
-
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
-import org.apache.freemarker.core.util._StringUtil;
-
-
-/**
- * An instruction that gets another template
- * and processes it within the current template.
- */
-final class Include extends TemplateElement {
-
-    private final Expression includedTemplateNameExp, encodingExp, parseExp, ignoreMissingExp;
-    private final String encoding;
-    private final Boolean parse;
-    private final Boolean ignoreMissingExpPrecalcedValue;
-
-    /**
-     * @param template the template that this <tt>#include</tt> is a part of.
-     * @param includedTemplateNameExp the path of the template to be included.
-     * @param encodingExp the encoding to be used or null, if it's the default.
-     * @param parseExp whether the template should be parsed (or is raw text)
-     */
-    Include(Template template,
-            Expression includedTemplateNameExp,
-            Expression encodingExp, Expression parseExp, Expression ignoreMissingExp) throws ParseException {
-        this.includedTemplateNameExp = includedTemplateNameExp;
-        
-        this.encodingExp = encodingExp;
-        if (encodingExp == null) {
-            encoding = null;
-        } else {
-            if (encodingExp.isLiteral()) {
-                try {
-                    TemplateModel tm = encodingExp.eval(null);
-                    if (!(tm instanceof TemplateScalarModel)) {
-                        throw new ParseException("Expected a string as the value of the \"encoding\" argument",
-                                encodingExp);
-                    }
-                    encoding = ((TemplateScalarModel) tm).getAsString();
-                } catch (TemplateException e) {
-                    // evaluation of literals must not throw a TemplateException
-                    throw new BugException(e);
-                }
-            } else {
-                encoding = null;
-            }
-        }
-        
-        this.parseExp = parseExp;
-        if (parseExp == null) {
-            parse = Boolean.TRUE;
-        } else {
-            if (parseExp.isLiteral()) {
-                try {
-                    if (parseExp instanceof StringLiteral) {
-                        // Legacy
-                        parse = Boolean.valueOf(_StringUtil.getYesNo(parseExp.evalAndCoerceToPlainText(null)));
-                    } else {
-                        try {
-                            parse = Boolean.valueOf(parseExp.evalToBoolean(template.getConfiguration()));
-                        } catch (NonBooleanException e) {
-                            throw new ParseException("Expected a boolean or string as the value of the parse attribute",
-                                    parseExp, e);
-                        }
-                    }
-                } catch (TemplateException e) {
-                    // evaluation of literals must not throw a TemplateException
-                    throw new BugException(e);
-                }
-            } else {
-                parse = null;
-            }
-        }
-        
-        this.ignoreMissingExp = ignoreMissingExp;
-        if (ignoreMissingExp != null && ignoreMissingExp.isLiteral()) {
-            try {
-                try {
-                    ignoreMissingExpPrecalcedValue = Boolean.valueOf(
-                            ignoreMissingExp.evalToBoolean(template.getConfiguration()));
-                } catch (NonBooleanException e) {
-                    throw new ParseException("Expected a boolean as the value of the \"ignore_missing\" attribute",
-                            ignoreMissingExp, e);
-                }
-            } catch (TemplateException e) {
-                // evaluation of literals must not throw a TemplateException
-                throw new BugException(e);
-            }
-        } else {
-            ignoreMissingExpPrecalcedValue = null;
-        }
-    }
-    
-    @Override
-    TemplateElement[] accept(Environment env) throws TemplateException, IOException {
-        final String includedTemplateName = includedTemplateNameExp.evalAndCoerceToPlainText(env);
-        final String fullIncludedTemplateName;
-        try {
-            fullIncludedTemplateName = env.toFullTemplateName(getTemplate().getName(), includedTemplateName);
-        } catch (MalformedTemplateNameException e) {
-            throw new _MiscTemplateException(e, env,
-                    "Malformed template name ", new _DelayedJQuote(e.getTemplateName()), ":\n",
-                    e.getMalformednessDescription());
-        }
-        
-        final String encoding = this.encoding != null
-                ? this.encoding
-                : (encodingExp != null
-                        ? encodingExp.evalAndCoerceToPlainText(env)
-                        : null);
-        
-        final boolean parse;
-        if (this.parse != null) {
-            parse = this.parse.booleanValue();
-        } else {
-            TemplateModel tm = parseExp.eval(env);
-            if (tm instanceof TemplateScalarModel) {
-                // Legacy
-                parse = getYesNo(parseExp, EvalUtil.modelToString((TemplateScalarModel) tm, parseExp, env));
-            } else {
-                parse = parseExp.modelToBoolean(tm, env);
-            }
-        }
-        
-        final boolean ignoreMissing;
-        if (ignoreMissingExpPrecalcedValue != null) {
-            ignoreMissing = ignoreMissingExpPrecalcedValue.booleanValue();
-        } else if (ignoreMissingExp != null) {
-            ignoreMissing = ignoreMissingExp.evalToBoolean(env);
-        } else {
-            ignoreMissing = false;
-        }
-        
-        final Template includedTemplate;
-        try {
-            includedTemplate = env.getTemplateForInclusion(fullIncludedTemplateName, encoding, parse, ignoreMissing);
-        } catch (IOException e) {
-            throw new _MiscTemplateException(e, env,
-                    "Template inclusion failed (for parameter value ",
-                    new _DelayedJQuote(includedTemplateName),
-                    "):\n", new _DelayedGetMessage(e));
-        }
-        
-        if (includedTemplate != null) {
-            env.include(includedTemplate);
-        }
-        return null;
-    }
-    
-    @Override
-    protected String dump(boolean canonical) {
-        StringBuilder buf = new StringBuilder();
-        if (canonical) buf.append('<');
-        buf.append(getNodeTypeSymbol());
-        buf.append(' ');
-        buf.append(includedTemplateNameExp.getCanonicalForm());
-        if (encodingExp != null) {
-            buf.append(" encoding=").append(encodingExp.getCanonicalForm());
-        }
-        if (parseExp != null) {
-            buf.append(" parse=").append(parseExp.getCanonicalForm());
-        }
-        if (ignoreMissingExp != null) {
-            buf.append(" ignore_missing=").append(ignoreMissingExp.getCanonicalForm());
-        }
-        if (canonical) buf.append("/>");
-        return buf.toString();
-    }
-
-    @Override
-    String getNodeTypeSymbol() {
-        return "#include";
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 3;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        switch (idx) {
-        case 0: return includedTemplateNameExp;
-        case 1: return parseExp;
-        case 2: return encodingExp;
-        case 3: return ignoreMissingExp;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        switch (idx) {
-        case 0: return ParameterRole.TEMPLATE_NAME;
-        case 1: return ParameterRole.PARSE_PARAMETER;
-        case 2: return ParameterRole.ENCODING_PARAMETER;
-        case 3: return ParameterRole.IGNORE_MISSING_PARAMETER;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }
-
-    @Override
-    boolean isNestedBlockRepeater() {
-        return false;
-    }
-
-    private boolean getYesNo(Expression exp, String s) throws TemplateException {
-        try {
-           return _StringUtil.getYesNo(s);
-        } catch (IllegalArgumentException iae) {
-            throw new _MiscTemplateException(exp,
-                     "Value must be boolean (or one of these strings: "
-                     + "\"n\", \"no\", \"f\", \"false\", \"y\", \"yes\", \"t\", \"true\"), but it was ",
-                     new _DelayedJQuote(s), ".");
-        }
-    }
-
-/*
-    boolean heedsOpeningWhitespace() {
-        return true;
-    }
-
-    boolean heedsTrailingWhitespace() {
-        return true;
-    }
-*/
-    
-    @Override
-    boolean isShownInStackTrace() {
-        return true;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Interpolation.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/Interpolation.java b/src/main/java/org/apache/freemarker/core/ast/Interpolation.java
deleted file mode 100644
index 573f3c2..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/Interpolation.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import org.apache.freemarker.core.TemplateException;
-
-abstract class Interpolation extends TemplateElement {
-
-    protected abstract String dump(boolean canonical, boolean inStringLiteral);
-
-    @Override
-    protected final String dump(boolean canonical) {
-        return dump(canonical, false);
-    }
-    
-    final String getCanonicalFormInStringLiteral() {
-        return dump(true, true);
-    }
-
-    /**
-     * Returns the already type-converted value that this interpolation will insert into the output.
-     * 
-     * @return A {@link String} or {@link TemplateMarkupOutputModel}. Not {@code null}.
-     */
-    protected abstract Object calculateInterpolatedStringOrMarkup(Environment env) throws TemplateException;
-
-    @Override
-    boolean isShownInStackTrace() {
-        return true;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Interpret.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/Interpret.java b/src/main/java/org/apache/freemarker/core/ast/Interpret.java
deleted file mode 100644
index 8c4274c..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/Interpret.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.Writer;
-import java.util.Map;
-
-import org.apache.freemarker.core.Template;
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.TemplateTransformModel;
-
-
-/**
- * A method that takes a parameter and evaluates it as a scalar,
- * then treats that scalar as template source code and returns a
- * transform model that evaluates the template in place.
- * The template inherits the configuration and environment of the executing
- * template. By default, its name will be equal to 
- * <tt>executingTemplate.getName() + "$anonymous_interpreted"</tt>. You can
- * specify another parameter to the method call in which case the
- * template name suffix is the specified id instead of "anonymous_interpreted".
- */
-class Interpret extends OutputFormatBoundBuiltIn {
-    
-    /**
-     * Constructs a template on-the-fly and returns it embedded in a
-     * {@link TemplateTransformModel}.
-     * 
-     * <p>The built-in has two arguments:
-     * the arguments passed to the method. It can receive at
-     * least one and at most two arguments, both must evaluate to a scalar. 
-     * The first scalar is interpreted as a template source code and a template
-     * is built from it. The second (optional) is used to give the generated
-     * template a name.
-     * 
-     * @return a {@link TemplateTransformModel} that when executed inside
-     * a <tt>&lt;transform></tt> block will process the generated template
-     * just as if it had been <tt>&lt;transform></tt>-ed at that point.
-     */
-    @Override
-    protected TemplateModel calculateResult(Environment env) throws TemplateException {
-        TemplateModel model = target.eval(env);
-        Expression sourceExpr = null;
-        String id = "anonymous_interpreted";
-        if (model instanceof TemplateSequenceModel) {
-            sourceExpr = ((Expression) new DynamicKeyName(target, new NumberLiteral(Integer.valueOf(0))).copyLocationFrom(target));
-            if (((TemplateSequenceModel) model).size() > 1) {
-                id = ((Expression) new DynamicKeyName(target, new NumberLiteral(Integer.valueOf(1))).copyLocationFrom(target)).evalAndCoerceToPlainText(env);
-            }
-        } else if (model instanceof TemplateScalarModel) {
-            sourceExpr = target;
-        } else {
-            throw new UnexpectedTypeException(
-                    target, model,
-                    "sequence or string", new Class[] { TemplateSequenceModel.class, TemplateScalarModel.class },
-                    env);
-        }
-        String templateSource = sourceExpr.evalAndCoerceToPlainText(env);
-        Template parentTemplate = env.getCurrentTemplate();
-        
-        final Template interpretedTemplate;
-        try {
-            ParserConfiguration pCfg = parentTemplate.getParserConfiguration();
-            // pCfg.outputFormat is exceptional: it's inherited from the lexical context
-            if (pCfg.getOutputFormat() != outputFormat) {
-                pCfg = new _ParserConfigurationWithInheritedFormat(
-                        pCfg, outputFormat, Integer.valueOf(autoEscapingPolicy));
-            }
-            interpretedTemplate = new Template(
-                    (parentTemplate.getName() != null ? parentTemplate.getName() : "nameless_template") + "->" + id,
-                    null,
-                    new StringReader(templateSource),
-                    parentTemplate.getConfiguration(), pCfg,
-                    null);
-        } catch (IOException e) {
-            throw new _MiscTemplateException(this, e, env, new Object[] {
-                        "Template parsing with \"?", key, "\" has failed with this error:\n\n",
-                        MessageUtil.EMBEDDED_MESSAGE_BEGIN,
-                        new _DelayedGetMessage(e),
-                        MessageUtil.EMBEDDED_MESSAGE_END,
-                        "\n\nThe failed expression:" });
-        }
-        
-        interpretedTemplate.setLocale(env.getLocale());
-        return new TemplateProcessorModel(interpretedTemplate);
-    }
-
-    private class TemplateProcessorModel
-    implements
-        TemplateTransformModel {
-        private final Template template;
-        
-        TemplateProcessorModel(Template template) {
-            this.template = template;
-        }
-        
-        @Override
-        public Writer getWriter(final Writer out, Map args) throws TemplateModelException, IOException {
-            try {
-                Environment env = Environment.getCurrentEnvironment();
-                boolean lastFIRE = env.setFastInvalidReferenceExceptions(false);
-                try {
-                    env.include(template);
-                } finally {
-                    env.setFastInvalidReferenceExceptions(lastFIRE);
-                }
-            } catch (Exception e) {
-                throw new _TemplateModelException(e,
-                        "Template created with \"?", key, "\" has stopped with this error:\n\n",
-                        MessageUtil.EMBEDDED_MESSAGE_BEGIN,
-                        new _DelayedGetMessage(e),
-                        MessageUtil.EMBEDDED_MESSAGE_END);
-            }
-    
-            return new Writer(out)
-            {
-                @Override
-                public void close() {
-                }
-                
-                @Override
-                public void flush() throws IOException {
-                    out.flush();
-                }
-                
-                @Override
-                public void write(char[] cbuf, int off, int len) throws IOException {
-                    out.write(cbuf, off, len);
-                }
-            };
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/InvalidFormatParametersException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/InvalidFormatParametersException.java b/src/main/java/org/apache/freemarker/core/ast/InvalidFormatParametersException.java
deleted file mode 100644
index a9f7a12..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/InvalidFormatParametersException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-/**
- * Used when creating {@link TemplateDateFormat}-s and {@link TemplateNumberFormat}-s to indicate that the parameters
- * part of the format string (like some kind of pattern) is malformed.
- * 
- * @since 2.3.24
- */
-public final class InvalidFormatParametersException extends InvalidFormatStringException {
-    
-    public InvalidFormatParametersException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public InvalidFormatParametersException(String message) {
-        this(message, null);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/InvalidFormatStringException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/InvalidFormatStringException.java b/src/main/java/org/apache/freemarker/core/ast/InvalidFormatStringException.java
deleted file mode 100644
index 61a7151..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/InvalidFormatStringException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-/**
- * Used when creating {@link TemplateDateFormat}-s and {@link TemplateNumberFormat}-s to indicate that the format
- * string (like the value of the {@code dateFormat} setting) is malformed.
- * 
- * @since 2.3.24
- */
-public abstract class InvalidFormatStringException extends TemplateValueFormatException {
-    
-    public InvalidFormatStringException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public InvalidFormatStringException(String message) {
-        this(message, null);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/InvalidReferenceException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/InvalidReferenceException.java b/src/main/java/org/apache/freemarker/core/ast/InvalidReferenceException.java
deleted file mode 100644
index 50b44dc..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/InvalidReferenceException.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import org.apache.freemarker.core.TemplateException;
-
-/**
- * A subclass of {@link TemplateException} that says that an FTL expression has evaluated to {@code null} or it refers
- * to something that doesn't exist. At least in FreeMarker 2.3.x these two cases aren't distinguished.
- */
-public class InvalidReferenceException extends TemplateException {
-
-    static final InvalidReferenceException FAST_INSTANCE;
-    static {
-        Environment prevEnv = Environment.getCurrentEnvironment();
-        try {
-            Environment.setCurrentEnvironment(null);
-            FAST_INSTANCE = new InvalidReferenceException(
-                    "Invalid reference. Details are unavilable, as this should have been handled by an FTL construct. "
-                    + "If it wasn't, that's problably a bug in FreeMarker.",
-                    null);
-        } finally {
-            Environment.setCurrentEnvironment(prevEnv);
-        }
-    }
-    
-    private static final Object[] TIP = {
-        "If the failing expression is known to be legally refer to something that's sometimes null or missing, "
-        + "either specify a default value like myOptionalVar!myDefault, or use ",
-        "<#if myOptionalVar??>", "when-present", "<#else>", "when-missing", "</#if>",
-        ". (These only cover the last step of the expression; to cover the whole expression, "
-        + "use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??"
-    };
-
-    private static final Object[] TIP_MISSING_ASSIGNMENT_TARGET = {
-            "If the target variable is known to be legally null or missing sometimes, instead of something like ",
-            "<#assign x += 1>", ", you could write ", "<#if x??>", "<#assign x += 1>", "</#if>",
-            " or ", "<#assign x = (x!0) + 1>"
-    };
-    
-    private static final String TIP_NO_DOLLAR =
-            "Variable references must not start with \"$\", unless the \"$\" is really part of the variable name.";
-
-    private static final String TIP_LAST_STEP_DOT =
-            "It's the step after the last dot that caused this error, not those before it.";
-
-    private static final String TIP_LAST_STEP_SQUARE_BRACKET =
-            "It's the final [] step that caused this error, not those before it.";
-    
-    private static final String TIP_JSP_TAGLIBS =
-            "The \"JspTaglibs\" variable isn't a core FreeMarker feature; "
-            + "it's only available when templates are invoked through org.apache.freemarker.servlet.FreemarkerServlet"
-            + " (or other custom FreeMarker-JSP integration solution).";
-    
-    /**
-     * Creates and invalid reference exception that contains no information about what was missing or null.
-     * As such, try to avoid this constructor.
-     */
-    public InvalidReferenceException(Environment env) {
-        super("Invalid reference: The expression has evaluated to null or refers to something that doesn't exist.",
-                env);
-    }
-
-    /**
-     * Creates and invalid reference exception that contains no programmatically extractable information about the
-     * blamed expression. As such, try to avoid this constructor, unless need to raise this expression from outside
-     * the FreeMarker core.
-     */
-    public InvalidReferenceException(String description, Environment env) {
-        super(description, env);
-    }
-
-    /**
-     * This is the recommended constructor, but it's only used internally, and has no backward compatibility guarantees.
-     * 
-     * @param expression The expression that evaluates to missing or null. The last step of the expression should be
-     *     the failing one, like in {@code goodStep.failingStep.furtherStep} it should only contain
-     *     {@code goodStep.failingStep}.
-     */
-    InvalidReferenceException(_ErrorDescriptionBuilder description, Environment env, Expression expression) {
-        super(null, env, expression, description);
-    }
-
-    /**
-     * Use this whenever possible, as it returns {@link #FAST_INSTANCE} instead of creating a new instance, when
-     * appropriate.
-     */
-    static InvalidReferenceException getInstance(Expression blamed, Environment env) {
-        if (env != null && env.getFastInvalidReferenceExceptions()) {
-            return FAST_INSTANCE;
-        } else {
-            if (blamed != null) {
-                final _ErrorDescriptionBuilder errDescBuilder
-                        = new _ErrorDescriptionBuilder("The following has evaluated to null or missing:").blame(blamed);
-                if (endsWithDollarVariable(blamed)) {
-                    errDescBuilder.tips(TIP_NO_DOLLAR, TIP);
-                } else if (blamed instanceof Dot) {
-                    final String rho = ((Dot) blamed).getRHO();
-                    String nameFixTip = null;
-                    if ("size".equals(rho)) {
-                        nameFixTip = "To query the size of a collection or map use ?size, like myList?size";
-                    } else if ("length".equals(rho)) {
-                        nameFixTip = "To query the length of a string use ?length, like myString?size";
-                    }
-                    errDescBuilder.tips(
-                            nameFixTip == null
-                                    ? new Object[] { TIP_LAST_STEP_DOT, TIP }
-                                    : new Object[] { TIP_LAST_STEP_DOT, nameFixTip, TIP });
-                } else if (blamed instanceof DynamicKeyName) {
-                    errDescBuilder.tips(TIP_LAST_STEP_SQUARE_BRACKET, TIP);
-                } else if (blamed instanceof Identifier
-                        && ((Identifier) blamed).getName().equals("JspTaglibs")) {
-                    errDescBuilder.tips(TIP_JSP_TAGLIBS, TIP);
-                } else {
-                    errDescBuilder.tip(TIP);
-                }
-                return new InvalidReferenceException(errDescBuilder, env, blamed);
-            } else {
-                return new InvalidReferenceException(env);
-            }
-        }
-    }
-    
-    /**
-     * Used for assignments that use operators like {@code +=}, when the target variable was null/missing. 
-     */
-    static InvalidReferenceException getInstance(String missingAssignedVarName, String assignmentOperator,
-            Environment env) {
-        if (env != null && env.getFastInvalidReferenceExceptions()) {
-            return FAST_INSTANCE;
-        } else {
-            final _ErrorDescriptionBuilder errDescBuilder = new _ErrorDescriptionBuilder(
-                            "The target variable of the assignment, ",
-                            new _DelayedJQuote(missingAssignedVarName),
-                            ", was null or missing, but the \"",
-                            assignmentOperator, "\" operator needs to get its value before assigning to it."
-                    );
-            if (missingAssignedVarName.startsWith("$")) {
-                errDescBuilder.tips(TIP_NO_DOLLAR, TIP_MISSING_ASSIGNMENT_TARGET);
-            } else {
-                errDescBuilder.tip(TIP_MISSING_ASSIGNMENT_TARGET);
-            }
-            return new InvalidReferenceException(errDescBuilder, env, null);
-        }
-    }
-
-    private static boolean endsWithDollarVariable(Expression blame) {
-        return blame instanceof Identifier && ((Identifier) blame).getName().startsWith("$")
-                || blame instanceof Dot && ((Dot) blame).getRHO().startsWith("$");
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Items.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/Items.java b/src/main/java/org/apache/freemarker/core/ast/Items.java
deleted file mode 100644
index 6f9fa40..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/Items.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.io.IOException;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.ast.IteratorBlock.IterationContext;
-import org.apache.freemarker.core.util._StringUtil;
-
-/**
- * An #items element.
- */
-class Items extends TemplateElement {
-
-    private final String loopVarName;
-    private final String loopVar2Name;
-
-    /**
-     * @param loopVar2Name
-     *            For non-hash listings always {@code null}, for hash listings {@code loopVarName} and
-     *            {@code loopVarName2} holds the key- and value loop variable names.
-     */
-    Items(String loopVarName, String loopVar2Name, TemplateElements children) {
-        this.loopVarName = loopVarName;
-        this.loopVar2Name = loopVar2Name;
-        setChildren(children);
-    }
-
-    @Override
-    TemplateElement[] accept(Environment env) throws TemplateException, IOException {
-        final IterationContext iterCtx = IteratorBlock.findEnclosingIterationContext(env, null);
-        if (iterCtx == null) {
-            // The parser should prevent this situation
-            throw new _MiscTemplateException(env,
-                    getNodeTypeSymbol(), " without iteration in context");
-        }
-        
-        iterCtx.loopForItemsElement(env, getChildBuffer(), loopVarName, loopVar2Name);
-        return null;
-    }
-
-    @Override
-    boolean isNestedBlockRepeater() {
-        return true;
-    }
-
-    @Override
-    protected String dump(boolean canonical) {
-        StringBuilder sb = new StringBuilder();
-        if (canonical) sb.append('<');
-        sb.append(getNodeTypeSymbol());
-        sb.append(" as ");
-        sb.append(_StringUtil.toFTLTopLevelIdentifierReference(loopVarName));
-        if (loopVar2Name != null) {
-            sb.append(", ");
-            sb.append(_StringUtil.toFTLTopLevelIdentifierReference(loopVar2Name));
-        }
-        if (canonical) {
-            sb.append('>');
-            sb.append(getChildrenCanonicalForm());
-            sb.append("</");
-            sb.append(getNodeTypeSymbol());
-            sb.append('>');
-        }
-        return sb.toString();
-    }
-
-    @Override
-    String getNodeTypeSymbol() {
-        return "#items";
-    }
-
-    @Override
-    int getParameterCount() {
-        return loopVar2Name != null ? 2 : 1;
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        switch (idx) {
-        case 0:
-            if (loopVarName == null) throw new IndexOutOfBoundsException();
-            return loopVarName;
-        case 1:
-            if (loopVar2Name == null) throw new IndexOutOfBoundsException();
-            return loopVar2Name;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        switch (idx) {
-        case 0:
-            if (loopVarName == null) throw new IndexOutOfBoundsException();
-            return ParameterRole.TARGET_LOOP_VARIABLE;
-        case 1:
-            if (loopVar2Name == null) throw new IndexOutOfBoundsException();
-            return ParameterRole.TARGET_LOOP_VARIABLE;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/IteratorBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ast/IteratorBlock.java b/src/main/java/org/apache/freemarker/core/ast/IteratorBlock.java
deleted file mode 100644
index 1ee3c0d..0000000
--- a/src/main/java/org/apache/freemarker/core/ast/IteratorBlock.java
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * 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.apache.freemarker.core.ast;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.TemplateBooleanModel;
-import org.apache.freemarker.core.model.TemplateCollectionModel;
-import org.apache.freemarker.core.model.TemplateHashModelEx;
-import org.apache.freemarker.core.model.TemplateHashModelEx2;
-import org.apache.freemarker.core.model.TemplateModel;
-import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateModelIterator;
-import org.apache.freemarker.core.model.TemplateScalarModel;
-import org.apache.freemarker.core.model.TemplateSequenceModel;
-import org.apache.freemarker.core.model.TemplateHashModelEx2.KeyValuePair;
-import org.apache.freemarker.core.model.TemplateHashModelEx2.KeyValuePairIterator;
-import org.apache.freemarker.core.model.impl.SimpleNumber;
-import org.apache.freemarker.core.util._StringUtil;
-
-/**
- * A #list (or #foreach) element, or pre-#else section of it inside a {@link ListElseContainer}.
- */
-final class IteratorBlock extends TemplateElement {
-
-    private final Expression listedExp;
-    private final String loopVarName;
-    private final String loopVar2Name;
-    private final boolean hashListing;
-    private final boolean forEach;
-
-    /**
-     * @param listedExp
-     *            a variable referring to a sequence or collection or extended hash to list
-     * @param loopVarName
-     *            The name of the variable that will hold the value of the current item when looping through listed value,
-     *            or {@code null} if we have a nested {@code #items}. If this is a hash listing then this variable will holds the value
-     *            of the hash key.
-     * @param loopVar2Name
-     *            The name of the variable that will hold the value of the current item when looping through the list,
-     *            or {@code null} if we have a nested {@code #items}. If this is a hash listing then it variable will hold the value
-     *            from the key-value pair.
-     * @param childrenBeforeElse
-     *            The nested content to execute if the listed value wasn't empty; can't be {@code null}. If the loop variable
-     *            was specified in the start tag, this is also what we will iterate over.
-     * @param hashListing
-     *            Whether this is a key-value pair listing, or a usual listing. This is properly set even if we have
-     *            a nested {@code #items}.
-     * @param forEach
-     *            Whether this is {@code #foreach} or a {@code #list}.
-     */
-    IteratorBlock(Expression listedExp,
-                  String loopVarName,
-                  String loopVar2Name,
-                  TemplateElements childrenBeforeElse,
-                  boolean hashListing,
-                  boolean forEach) {
-        this.listedExp = listedExp;
-        this.loopVarName = loopVarName;
-        this.loopVar2Name = loopVar2Name;
-        setChildren(childrenBeforeElse);
-        this.hashListing = hashListing;
-        this.forEach = forEach;
-    }
-    
-    boolean isHashListing() {
-        return hashListing;
-    }
-
-    @Override
-    TemplateElement[] accept(Environment env) throws TemplateException, IOException {
-        acceptWithResult(env);
-        return null;
-    }
-    
-    boolean acceptWithResult(Environment env) throws TemplateException, IOException {
-        TemplateModel listedValue = listedExp.eval(env);
-        if (listedValue == null) {
-            listedExp.assertNonNull(null, env);
-        }
-
-        return env.visitIteratorBlock(new IterationContext(listedValue, loopVarName, loopVar2Name));
-    }
-
-    /**
-     * @param loopVariableName
-     *            Then name of the loop variable whose context we are looking for, or {@code null} if we simply look for
-     *            the innermost context.
-     * @return The matching context or {@code null} if no such context exists.
-     */
-    static IterationContext findEnclosingIterationContext(Environment env, String loopVariableName)
-            throws _MiscTemplateException {
-        LocalContextStack ctxStack = env.getLocalContextStack();
-        if (ctxStack != null) {
-            for (int i = ctxStack.size() - 1; i >= 0; i--) {
-                Object ctx = ctxStack.get(i);
-                if (ctx instanceof IterationContext
-                        && (loopVariableName == null
-                            || loopVariableName.equals(((IterationContext) ctx).getLoopVariableName())
-                            || loopVariableName.equals(((IterationContext) ctx).getLoopVariable2Name())
-                            )) {
-                    return (IterationContext) ctx;
-                }
-            }
-        }
-        return null;
-    }
-    
-    @Override
-    protected String dump(boolean canonical) {
-        StringBuilder buf = new StringBuilder();
-        if (canonical) buf.append('<');
-        buf.append(getNodeTypeSymbol());
-        buf.append(' ');
-        if (forEach) {
-            buf.append(_StringUtil.toFTLTopLevelIdentifierReference(loopVarName));
-            buf.append(" in ");
-            buf.append(listedExp.getCanonicalForm());
-        } else {
-            buf.append(listedExp.getCanonicalForm());
-            if (loopVarName != null) {
-                buf.append(" as ");
-                buf.append(_StringUtil.toFTLTopLevelIdentifierReference(loopVarName));
-                if (loopVar2Name != null) {
-                    buf.append(", ");
-                    buf.append(_StringUtil.toFTLTopLevelIdentifierReference(loopVar2Name));
-                }
-            }
-        }
-        if (canonical) {
-            buf.append(">");
-            buf.append(getChildrenCanonicalForm());
-            if (!(getParentElement() instanceof ListElseContainer)) {
-                buf.append("</");
-                buf.append(getNodeTypeSymbol());
-                buf.append('>');
-            }
-        }
-        return buf.toString();
-    }
-    
-    @Override
-    int getParameterCount() {
-        return 1 + (loopVarName != null ? 1 : 0) + (loopVar2Name != null ? 1 : 0);
-    }
-
-    @Override
-    Object getParameterValue(int idx) {
-        switch (idx) {
-        case 0:
-            return listedExp;
-        case 1:
-            if (loopVarName == null) throw new IndexOutOfBoundsException();
-            return loopVarName;
-        case 2:
-            if (loopVar2Name == null) throw new IndexOutOfBoundsException();
-            return loopVar2Name;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }
-
-    @Override
-    ParameterRole getParameterRole(int idx) {
-        switch (idx) {
-        case 0:
-            return ParameterRole.LIST_SOURCE;
-        case 1:
-            if (loopVarName == null) throw new IndexOutOfBoundsException();
-            return ParameterRole.TARGET_LOOP_VARIABLE;
-        case 2:
-            if (loopVar2Name == null) throw new IndexOutOfBoundsException();
-            return ParameterRole.TARGET_LOOP_VARIABLE;
-        default: throw new IndexOutOfBoundsException();
-        }
-    }    
-    
-    @Override
-    String getNodeTypeSymbol() {
-        return forEach ? "#foreach" : "#list";
-    }
-
-    @Override
-    boolean isNestedBlockRepeater() {
-        return loopVarName != null;
-    }
-
-    /**
-     * Holds the context of a #list (or #forEach) directive.
-     */
-    class IterationContext implements LocalContext {
-        
-        private static final String LOOP_STATE_HAS_NEXT = "_has_next"; // lenght: 9
-        private static final String LOOP_STATE_INDEX = "_index"; // length 6
-        
-        private Object openedIterator;
-        private boolean hasNext;
-        private TemplateModel loopVar;
-        private TemplateModel loopVar2;
-        private int index;
-        private boolean alreadyEntered;
-        private Collection localVarNames = null;
-        
-        /** If the {@code #list} has nested {@code #items}, it's {@code null} outside the {@code #items}. */
-        private String loopVarName;
-        /** Used if we list key-value pairs */
-        private String loopVar2Name;
-        
-        private final TemplateModel listedValue;
-        
-        public IterationContext(TemplateModel listedValue, String loopVarName, String loopVar2Name) {
-            this.listedValue = listedValue;
-            this.loopVarName = loopVarName;
-            this.loopVar2Name = loopVar2Name;
-        }
-        
-        boolean accept(Environment env) throws TemplateException, IOException {
-            return executeNestedContent(env, getChildBuffer());
-        }
-
-        void loopForItemsElement(Environment env, TemplateElement[] childBuffer, String loopVarName, String loopVar2Name)
-                    throws NonSequenceOrCollectionException, TemplateModelException, InvalidReferenceException,
-                    TemplateException, IOException {
-            try {
-                if (alreadyEntered) {
-                    throw new _MiscTemplateException(env,
-                            "The #items directive was already entered earlier for this listing.");
-                }
-                alreadyEntered = true;
-                this.loopVarName = loopVarName;
-                this.loopVar2Name = loopVar2Name;
-                executeNestedContent(env, childBuffer);
-            } finally {
-                this.loopVarName = null;
-                this.loopVar2Name = null;
-            }
-        }
-
-        /**
-         * Executes the given block for the {@link #listedValue}: if {@link #loopVarName} is non-{@code null}, then for
-         * each list item once, otherwise once if {@link #listedValue} isn't empty.
-         */
-        private boolean executeNestedContent(Environment env, TemplateElement[] childBuffer)
-                throws TemplateModelException, TemplateException, IOException, NonSequenceOrCollectionException,
-                InvalidReferenceException {
-            return !hashListing
-                    ? executedNestedContentForCollOrSeqListing(env, childBuffer)
-                    : executedNestedContentForHashListing(env, childBuffer);
-        }
-
-        private boolean executedNestedContentForCollOrSeqListing(Environment env, TemplateElement[] childBuffer)
-                throws TemplateModelException, IOException, TemplateException,
-                NonSequenceOrCollectionException, InvalidReferenceException {
-            final boolean listNotEmpty;
-            if (listedValue instanceof TemplateCollectionModel) {
-                final TemplateCollectionModel collModel = (TemplateCollectionModel) listedValue;
-                final TemplateModelIterator iterModel
-                        = openedIterator == null ? collModel.iterator()
-                                : ((TemplateModelIterator) openedIterator);
-                listNotEmpty = iterModel.hasNext();
-                if (listNotEmpty) {
-                    if (loopVarName != null) {
-                        try {
-                            do {
-                                loopVar = iterModel.next();
-                                hasNext = iterModel.hasNext();
-                                env.visit(childBuffer);
-                                index++;
-                            } while (hasNext);
-                        } catch (BreakInstruction.Break br) {
-                            // Silently exit loop
-                        }
-                        openedIterator = null;
-                    } else {
-                        // We must reuse this later, because TemplateCollectionModel-s that wrap an Iterator only
-                        // allow one iterator() call.
-                        openedIterator = iterModel;
-                        env.visit(childBuffer);
-                    }
-                }
-            } else if (listedValue instanceof TemplateSequenceModel) {
-                final TemplateSequenceModel seqModel = (TemplateSequenceModel) listedValue;
-                final int size = seqModel.size();
-                listNotEmpty = size != 0;
-                if (listNotEmpty) {
-                    if (loopVarName != null) {
-                        try {
-                            for (index = 0; index < size; index++) {
-                                loopVar = seqModel.get(index);
-                                hasNext = (size > index + 1);
-                                env.visit(childBuffer);
-                            }
-                        } catch (BreakInstruction.Break br) {
-                            // Silently exit loop
-                        }
-                    } else {
-                        env.visit(childBuffer);
-                    }
-                }
-            } else if (listedValue instanceof TemplateHashModelEx
-                    && !NonSequenceOrCollectionException.isWrappedIterable(listedValue)) {
-                throw new NonSequenceOrCollectionException(env,
-                        new _ErrorDescriptionBuilder("The value you try to list is ",
-                                new _DelayedAOrAn(new _DelayedFTLTypeDescription(listedValue)),
-                                ", thus you must specify two loop variables after the \"as\"; one for the key, and "
-                                + "another for the value, like ", "<#... as k, v>", ")."
-                                ));
-            } else {
-                throw new NonSequenceOrCollectionException(
-                        listedExp, listedValue, env);
-            }
-            return listNotEmpty;
-        }
-
-        private boolean executedNestedContentForHashListing(Environment env, TemplateElement[] childBuffer)
-                throws TemplateModelException, IOException, TemplateException {
-            final boolean hashNotEmpty;
-            if (listedValue instanceof TemplateHashModelEx) {
-                TemplateHashModelEx listedHash = (TemplateHashModelEx) listedValue; 
-                if (listedHash instanceof TemplateHashModelEx2) {
-                    KeyValuePairIterator kvpIter
-                            = openedIterator == null ? ((TemplateHashModelEx2) listedHash).keyValuePairIterator()
-                                    : (KeyValuePairIterator) openedIterator;
-                    hashNotEmpty = kvpIter.hasNext();
-                    if (hashNotEmpty) {
-                        if (loopVarName != null) {
-                            try {
-                                do {
-                                    KeyValuePair kvp = kvpIter.next();
-                                    loopVar = kvp.getKey();
-                                    loopVar2 = kvp.getValue();
-                                    hasNext = kvpIter.hasNext();
-                                    env.visit(childBuffer);
-                                    index++;
-                                } while (hasNext);
-                            } catch (BreakInstruction.Break br) {
-                                // Silently exit loop
-                            }
-                            openedIterator = null;
-                        } else {
-                            // We will reuse this at the #iterms
-                            openedIterator = kvpIter;
-                            env.visit(childBuffer);
-                        }
-                    }
-                } else { //  not a TemplateHashModelEx2, but still a TemplateHashModelEx
-                    TemplateModelIterator keysIter = listedHash.keys().iterator();
-                    hashNotEmpty = keysIter.hasNext();
-                    if (hashNotEmpty) {
-                        if (loopVarName != null) {
-                            try {
-                                do {
-                                    loopVar = keysIter.next();
-                                    if (!(loopVar instanceof TemplateScalarModel)) {
-                                        throw new NonStringException(env,
-                                                new _ErrorDescriptionBuilder(
-                                                        "When listing key-value pairs of traditional hash "
-                                                        + "implementations, all keys must be strings, but one of them "
-                                                        + "was ",
-                                                        new _DelayedAOrAn(new _DelayedFTLTypeDescription(loopVar)), "."
-                                                        ).tip("The listed value's TemplateModel class was ",
-                                                                new _DelayedShortClassName(listedValue.getClass()),
-                                                                ", which doesn't implement ",
-                                                                new _DelayedShortClassName(TemplateHashModelEx2.class),
-                                                                ", which leads to this restriction."));
-                                    }
-                                    loopVar2 = listedHash.get(((TemplateScalarModel) loopVar).getAsString());
-                                    hasNext = keysIter.hasNext();
-                                    env.visit(childBuffer);
-                                    index++;
-                                } while (hasNext);
-                            } catch (BreakInstruction.Break br) {
-                                // Silently exit loop
-                            }
-                        } else {
-                            env.visit(childBuffer);
-                        }
-                    }
-                }
-            } else if (listedValue instanceof TemplateCollectionModel
-                    || listedValue instanceof TemplateSequenceModel) {
-                throw new NonSequenceOrCollectionException(env,
-                        new _ErrorDescriptionBuilder("The value you try to list is ",
-                                new _DelayedAOrAn(new _DelayedFTLTypeDescription(listedValue)),
-                                ", thus you must specify only one loop variable after the \"as\" (there's no separate "
-                                + "key and value)."
-                                ));
-            } else {
-                throw new NonExtendedHashException(
-                        listedExp, listedValue, env);
-            }
-            return hashNotEmpty;
-        }
-
-        String getLoopVariableName() {
-            return loopVarName;
-        }
-
-        String getLoopVariable2Name() {
-            return loopVar2Name;
-        }
-        
-        @Override
-        public TemplateModel getLocalVariable(String name) {
-            String loopVarName = this.loopVarName;
-            if (loopVarName != null && name.startsWith(loopVarName)) {
-                switch(name.length() - loopVarName.length()) {
-                    case 0: 
-                        return loopVar;
-                    case 6: 
-                        if (name.endsWith(LOOP_STATE_INDEX)) {
-                            return new SimpleNumber(index);
-                        }
-                        break;
-                    case 9: 
-                        if (name.endsWith(LOOP_STATE_HAS_NEXT)) {
-                            return hasNext ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
-                        }
-                        break;
-                }
-            }
-            
-            if (name.equals(loopVar2Name)) {
-                return loopVar2;
-            }
-            
-            return null;
-        }
-        
-        @Override
-        public Collection getLocalVariableNames() {
-            String loopVarName = this.loopVarName;
-            if (loopVarName != null) {
-                if (localVarNames == null) {
-                    localVarNames = new ArrayList(3);
-                    localVarNames.add(loopVarName);
-                    localVarNames.add(loopVarName + LOOP_STATE_INDEX);
-                    localVarNames.add(loopVarName + LOOP_STATE_HAS_NEXT);
-                }
-                return localVarNames;
-            } else {
-                return Collections.EMPTY_LIST;
-            }
-        }
-
-        boolean hasNext() {
-            return hasNext;
-        }
-        
-        int getIndex() {
-            return index;
-        }
-        
-    }
-    
-}



Mime
View raw message