You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/02/23 21:35:50 UTC
[23/54] [partial] incubator-freemarker git commit: Unifying the
o.a.f.core and o.a.f.core.ast
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><transform></tt> block will process the generated template
- * just as if it had been <tt><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;
- }
-
- }
-
-}