http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/AndExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/AndExpression.java b/src/main/java/org/apache/freemarker/core/ast/AndExpression.java deleted file mode 100644 index 16a3cd3..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/AndExpression.java +++ /dev/null @@ -1,81 +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; - -final class AndExpression extends BooleanExpression { - - private final Expression lho; - private final Expression rho; - - AndExpression(Expression lho, Expression rho) { - this.lho = lho; - this.rho = rho; - } - - @Override - boolean evalToBoolean(Environment env) throws TemplateException { - return lho.evalToBoolean(env) && rho.evalToBoolean(env); - } - - @Override - public String getCanonicalForm() { - return lho.getCanonicalForm() + " && " + rho.getCanonicalForm(); - } - - @Override - String getNodeTypeSymbol() { - return "&&"; - } - - @Override - boolean isLiteral() { - return constantValue != null || (lho.isLiteral() && rho.isLiteral()); - } - - @Override - protected Expression deepCloneWithIdentifierReplaced_inner( - String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) { - return new AndExpression( - lho.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState), - rho.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState)); - } - - @Override - int getParameterCount() { - return 2; - } - - @Override - Object getParameterValue(int idx) { - switch (idx) { - case 0: return lho; - case 1: return rho; - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - ParameterRole getParameterRole(int idx) { - return ParameterRole.forBinaryOperatorOperand(idx); - } - -} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ArithmeticEngine.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/ArithmeticEngine.java b/src/main/java/org/apache/freemarker/core/ast/ArithmeticEngine.java deleted file mode 100644 index 6b2d299..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/ArithmeticEngine.java +++ /dev/null @@ -1,549 +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.math.BigDecimal; -import java.math.BigInteger; -import java.util.HashMap; -import java.util.Map; - -import org.apache.freemarker.core.TemplateException; -import org.apache.freemarker.core.util._NumberUtil; -import org.apache.freemarker.core.util._StringUtil; - -/** - * Class to perform arithmetic operations. - */ - -public abstract class ArithmeticEngine { - - /** - * Arithmetic engine that converts all numbers to {@link BigDecimal} and - * then operates on them. This is FreeMarker's default arithmetic engine. - */ - public static final BigDecimalEngine BIGDECIMAL_ENGINE = new BigDecimalEngine(); - /** - * Arithmetic engine that uses (more-or-less) the widening conversions of - * Java language to determine the type of result of operation, instead of - * converting everything to BigDecimal up front. - */ - public static final ConservativeEngine CONSERVATIVE_ENGINE = new ConservativeEngine(); - - public abstract int compareNumbers(Number first, Number second) throws TemplateException; - public abstract Number add(Number first, Number second) throws TemplateException; - public abstract Number subtract(Number first, Number second) throws TemplateException; - public abstract Number multiply(Number first, Number second) throws TemplateException; - public abstract Number divide(Number first, Number second) throws TemplateException; - public abstract Number modulus(Number first, Number second) throws TemplateException; - - /** - * Should be able to parse all FTL numerical literals, Java Double toString results, and XML Schema numbers. - * This means these should be parsed successfully, except if the arithmetical engine - * couldn't support the resulting value anyway (such as NaN, infinite, even non-integers): - * {@code -123.45}, {@code 1.5e3}, {@code 1.5E3}, {@code 0005}, {@code +0}, {@code -0}, {@code NaN}, - * {@code INF}, {@code -INF}, {@code Infinity}, {@code -Infinity}. - */ - public abstract Number toNumber(String s); - - protected int minScale = 12; - protected int maxScale = 12; - protected int roundingPolicy = BigDecimal.ROUND_HALF_UP; - - /** - * Sets the minimal scale to use when dividing BigDecimal numbers. Default - * value is 12. - */ - public void setMinScale(int minScale) { - if (minScale < 0) { - throw new IllegalArgumentException("minScale < 0"); - } - this.minScale = minScale; - } - - /** - * Sets the maximal scale to use when multiplying BigDecimal numbers. - * Default value is 100. - */ - public void setMaxScale(int maxScale) { - if (maxScale < minScale) { - throw new IllegalArgumentException("maxScale < minScale"); - } - this.maxScale = maxScale; - } - - public void setRoundingPolicy(int roundingPolicy) { - if (roundingPolicy != BigDecimal.ROUND_CEILING - && roundingPolicy != BigDecimal.ROUND_DOWN - && roundingPolicy != BigDecimal.ROUND_FLOOR - && roundingPolicy != BigDecimal.ROUND_HALF_DOWN - && roundingPolicy != BigDecimal.ROUND_HALF_EVEN - && roundingPolicy != BigDecimal.ROUND_HALF_UP - && roundingPolicy != BigDecimal.ROUND_UNNECESSARY - && roundingPolicy != BigDecimal.ROUND_UP) { - throw new IllegalArgumentException("invalid rounding policy"); - } - - this.roundingPolicy = roundingPolicy; - } - - /** - * This is the default arithmetic engine in FreeMarker. It converts every - * number it receives into {@link BigDecimal}, then operates on these - * converted {@link BigDecimal}s. - */ - public static class BigDecimalEngine - extends - ArithmeticEngine { - @Override - public int compareNumbers(Number first, Number second) { - // We try to find the result based on the sign (+/-/0) first, because: - // - It's much faster than converting to BigDecial, and comparing to 0 is the most common comparison. - // - It doesn't require any type conversions, and thus things like "Infinity > 0" won't fail. - int firstSignum = _NumberUtil.getSignum(first); - int secondSignum = _NumberUtil.getSignum(second); - if (firstSignum != secondSignum) { - return firstSignum < secondSignum ? -1 : (firstSignum > secondSignum ? 1 : 0); - } else if (firstSignum == 0 && secondSignum == 0) { - return 0; - } else { - BigDecimal left = toBigDecimal(first); - BigDecimal right = toBigDecimal(second); - return left.compareTo(right); - } - } - - @Override - public Number add(Number first, Number second) { - BigDecimal left = toBigDecimal(first); - BigDecimal right = toBigDecimal(second); - return left.add(right); - } - - @Override - public Number subtract(Number first, Number second) { - BigDecimal left = toBigDecimal(first); - BigDecimal right = toBigDecimal(second); - return left.subtract(right); - } - - @Override - public Number multiply(Number first, Number second) { - BigDecimal left = toBigDecimal(first); - BigDecimal right = toBigDecimal(second); - BigDecimal result = left.multiply(right); - if (result.scale() > maxScale) { - result = result.setScale(maxScale, roundingPolicy); - } - return result; - } - - @Override - public Number divide(Number first, Number second) { - BigDecimal left = toBigDecimal(first); - BigDecimal right = toBigDecimal(second); - return divide(left, right); - } - - @Override - public Number modulus(Number first, Number second) { - long left = first.longValue(); - long right = second.longValue(); - return Long.valueOf(left % right); - } - - @Override - public Number toNumber(String s) { - return toBigDecimalOrDouble(s); - } - - private BigDecimal divide(BigDecimal left, BigDecimal right) { - int scale1 = left.scale(); - int scale2 = right.scale(); - int scale = Math.max(scale1, scale2); - scale = Math.max(minScale, scale); - return left.divide(right, scale, roundingPolicy); - } - } - - /** - * An arithmetic engine that conservatively widens the operation arguments - * to extent that they can hold the result of the operation. Widening - * conversions occur in following situations: - * <ul> - * <li>byte and short are always widened to int (alike to Java language).</li> - * <li>To preserve magnitude: when operands are of different types, the - * result type is the type of the wider operand.</li> - * <li>to avoid overflows: if add, subtract, or multiply would overflow on - * integer types, the result is widened from int to long, or from long to - * BigInteger.</li> - * <li>to preserve fractional part: if a division of integer types would - * have a fractional part, int and long are converted to double, and - * BigInteger is converted to BigDecimal. An operation on a float and a - * long results in a double. An operation on a float or double and a - * BigInteger results in a BigDecimal.</li> - * </ul> - */ - public static class ConservativeEngine extends ArithmeticEngine { - private static final int INTEGER = 0; - private static final int LONG = 1; - private static final int FLOAT = 2; - private static final int DOUBLE = 3; - private static final int BIGINTEGER = 4; - private static final int BIGDECIMAL = 5; - - private static final Map classCodes = createClassCodesMap(); - - @Override - public int compareNumbers(Number first, Number second) throws TemplateException { - switch(getCommonClassCode(first, second)) { - case INTEGER: { - int n1 = first.intValue(); - int n2 = second.intValue(); - return n1 < n2 ? -1 : (n1 == n2 ? 0 : 1); - } - case LONG: { - long n1 = first.longValue(); - long n2 = second.longValue(); - return n1 < n2 ? -1 : (n1 == n2 ? 0 : 1); - } - case FLOAT: { - float n1 = first.floatValue(); - float n2 = second.floatValue(); - return n1 < n2 ? -1 : (n1 == n2 ? 0 : 1); - } - case DOUBLE: { - double n1 = first.doubleValue(); - double n2 = second.doubleValue(); - return n1 < n2 ? -1 : (n1 == n2 ? 0 : 1); - } - case BIGINTEGER: { - BigInteger n1 = toBigInteger(first); - BigInteger n2 = toBigInteger(second); - return n1.compareTo(n2); - } - case BIGDECIMAL: { - BigDecimal n1 = toBigDecimal(first); - BigDecimal n2 = toBigDecimal(second); - return n1.compareTo(n2); - } - } - // Make the compiler happy. getCommonClassCode() is guaranteed to - // return only above codes, or throw an exception. - throw new Error(); - } - - @Override - public Number add(Number first, Number second) throws TemplateException { - switch(getCommonClassCode(first, second)) { - case INTEGER: { - int n1 = first.intValue(); - int n2 = second.intValue(); - int n = n1 + n2; - return - ((n ^ n1) < 0 && (n ^ n2) < 0) // overflow check - ? Long.valueOf(((long) n1) + n2) - : Integer.valueOf(n); - } - case LONG: { - long n1 = first.longValue(); - long n2 = second.longValue(); - long n = n1 + n2; - return - ((n ^ n1) < 0 && (n ^ n2) < 0) // overflow check - ? toBigInteger(first).add(toBigInteger(second)) - : Long.valueOf(n); - } - case FLOAT: { - return Float.valueOf(first.floatValue() + second.floatValue()); - } - case DOUBLE: { - return Double.valueOf(first.doubleValue() + second.doubleValue()); - } - case BIGINTEGER: { - BigInteger n1 = toBigInteger(first); - BigInteger n2 = toBigInteger(second); - return n1.add(n2); - } - case BIGDECIMAL: { - BigDecimal n1 = toBigDecimal(first); - BigDecimal n2 = toBigDecimal(second); - return n1.add(n2); - } - } - // Make the compiler happy. getCommonClassCode() is guaranteed to - // return only above codes, or throw an exception. - throw new Error(); - } - - @Override - public Number subtract(Number first, Number second) throws TemplateException { - switch(getCommonClassCode(first, second)) { - case INTEGER: { - int n1 = first.intValue(); - int n2 = second.intValue(); - int n = n1 - n2; - return - ((n ^ n1) < 0 && (n ^ ~n2) < 0) // overflow check - ? Long.valueOf(((long) n1) - n2) - : Integer.valueOf(n); - } - case LONG: { - long n1 = first.longValue(); - long n2 = second.longValue(); - long n = n1 - n2; - return - ((n ^ n1) < 0 && (n ^ ~n2) < 0) // overflow check - ? toBigInteger(first).subtract(toBigInteger(second)) - : Long.valueOf(n); - } - case FLOAT: { - return Float.valueOf(first.floatValue() - second.floatValue()); - } - case DOUBLE: { - return Double.valueOf(first.doubleValue() - second.doubleValue()); - } - case BIGINTEGER: { - BigInteger n1 = toBigInteger(first); - BigInteger n2 = toBigInteger(second); - return n1.subtract(n2); - } - case BIGDECIMAL: { - BigDecimal n1 = toBigDecimal(first); - BigDecimal n2 = toBigDecimal(second); - return n1.subtract(n2); - } - } - // Make the compiler happy. getCommonClassCode() is guaranteed to - // return only above codes, or throw an exception. - throw new Error(); - } - - @Override - public Number multiply(Number first, Number second) throws TemplateException { - switch(getCommonClassCode(first, second)) { - case INTEGER: { - int n1 = first.intValue(); - int n2 = second.intValue(); - int n = n1 * n2; - return - n1 == 0 || n / n1 == n2 // overflow check - ? Integer.valueOf(n) - : Long.valueOf(((long) n1) * n2); - } - case LONG: { - long n1 = first.longValue(); - long n2 = second.longValue(); - long n = n1 * n2; - return - n1 == 0L || n / n1 == n2 // overflow check - ? Long.valueOf(n) - : toBigInteger(first).multiply(toBigInteger(second)); - } - case FLOAT: { - return Float.valueOf(first.floatValue() * second.floatValue()); - } - case DOUBLE: { - return Double.valueOf(first.doubleValue() * second.doubleValue()); - } - case BIGINTEGER: { - BigInteger n1 = toBigInteger(first); - BigInteger n2 = toBigInteger(second); - return n1.multiply(n2); - } - case BIGDECIMAL: { - BigDecimal n1 = toBigDecimal(first); - BigDecimal n2 = toBigDecimal(second); - BigDecimal r = n1.multiply(n2); - return r.scale() > maxScale ? r.setScale(maxScale, roundingPolicy) : r; - } - } - // Make the compiler happy. getCommonClassCode() is guaranteed to - // return only above codes, or throw an exception. - throw new Error(); - } - - @Override - public Number divide(Number first, Number second) throws TemplateException { - switch(getCommonClassCode(first, second)) { - case INTEGER: { - int n1 = first.intValue(); - int n2 = second.intValue(); - if (n1 % n2 == 0) { - return Integer.valueOf(n1 / n2); - } - return Double.valueOf(((double) n1) / n2); - } - case LONG: { - long n1 = first.longValue(); - long n2 = second.longValue(); - if (n1 % n2 == 0) { - return Long.valueOf(n1 / n2); - } - return Double.valueOf(((double) n1) / n2); - } - case FLOAT: { - return Float.valueOf(first.floatValue() / second.floatValue()); - } - case DOUBLE: { - return Double.valueOf(first.doubleValue() / second.doubleValue()); - } - case BIGINTEGER: { - BigInteger n1 = toBigInteger(first); - BigInteger n2 = toBigInteger(second); - BigInteger[] divmod = n1.divideAndRemainder(n2); - if (divmod[1].equals(BigInteger.ZERO)) { - return divmod[0]; - } else { - BigDecimal bd1 = new BigDecimal(n1); - BigDecimal bd2 = new BigDecimal(n2); - return bd1.divide(bd2, minScale, roundingPolicy); - } - } - case BIGDECIMAL: { - BigDecimal n1 = toBigDecimal(first); - BigDecimal n2 = toBigDecimal(second); - int scale1 = n1.scale(); - int scale2 = n2.scale(); - int scale = Math.max(scale1, scale2); - scale = Math.max(minScale, scale); - return n1.divide(n2, scale, roundingPolicy); - } - } - // Make the compiler happy. getCommonClassCode() is guaranteed to - // return only above codes, or throw an exception. - throw new Error(); - } - - @Override - public Number modulus(Number first, Number second) throws TemplateException { - switch(getCommonClassCode(first, second)) { - case INTEGER: { - return Integer.valueOf(first.intValue() % second.intValue()); - } - case LONG: { - return Long.valueOf(first.longValue() % second.longValue()); - } - case FLOAT: { - return Float.valueOf(first.floatValue() % second.floatValue()); - } - case DOUBLE: { - return Double.valueOf(first.doubleValue() % second.doubleValue()); - } - case BIGINTEGER: { - BigInteger n1 = toBigInteger(first); - BigInteger n2 = toBigInteger(second); - return n1.mod(n2); - } - case BIGDECIMAL: { - throw new _MiscTemplateException("Can't calculate remainder on BigDecimals"); - } - } - // Make the compiler happy. getCommonClassCode() is guaranteed to - // return only above codes, or throw an exception. - throw new BugException(); - } - - @Override - public Number toNumber(String s) { - Number n = toBigDecimalOrDouble(s); - return n instanceof BigDecimal ? _NumberUtil.optimizeNumberRepresentation(n) : n; - } - - private static Map createClassCodesMap() { - Map map = new HashMap(17); - Integer intcode = Integer.valueOf(INTEGER); - map.put(Byte.class, intcode); - map.put(Short.class, intcode); - map.put(Integer.class, intcode); - map.put(Long.class, Integer.valueOf(LONG)); - map.put(Float.class, Integer.valueOf(FLOAT)); - map.put(Double.class, Integer.valueOf(DOUBLE)); - map.put(BigInteger.class, Integer.valueOf(BIGINTEGER)); - map.put(BigDecimal.class, Integer.valueOf(BIGDECIMAL)); - return map; - } - - private static int getClassCode(Number num) throws TemplateException { - try { - return ((Integer) classCodes.get(num.getClass())).intValue(); - } catch (NullPointerException e) { - if (num == null) { - throw new _MiscTemplateException("The Number object was null."); - } else { - throw new _MiscTemplateException("Unknown number type ", num.getClass().getName()); - } - } - } - - private static int getCommonClassCode(Number num1, Number num2) throws TemplateException { - int c1 = getClassCode(num1); - int c2 = getClassCode(num2); - int c = c1 > c2 ? c1 : c2; - // If BigInteger is combined with a Float or Double, the result is a - // BigDecimal instead of BigInteger in order not to lose the - // fractional parts. If Float is combined with Long, the result is a - // Double instead of Float to preserve the bigger bit width. - switch(c) { - case FLOAT: { - if ((c1 < c2 ? c1 : c2) == LONG) { - return DOUBLE; - } - break; - } - case BIGINTEGER: { - int min = c1 < c2 ? c1 : c2; - if (min == DOUBLE || min == FLOAT) { - return BIGDECIMAL; - } - break; - } - } - return c; - } - - private static BigInteger toBigInteger(Number num) { - return num instanceof BigInteger ? (BigInteger) num : new BigInteger(num.toString()); - } - } - - private static BigDecimal toBigDecimal(Number num) { - try { - return num instanceof BigDecimal ? (BigDecimal) num : new BigDecimal(num.toString()); - } catch (NumberFormatException e) { - // The exception message is useless, so we add a new one: - throw new NumberFormatException("Can't parse this as BigDecimal number: " + _StringUtil.jQuote(num)); - } - } - - private static Number toBigDecimalOrDouble(String s) { - if (s.length() > 2) { - char c = s.charAt(0); - if (c == 'I' && (s.equals("INF") || s.equals("Infinity"))) { - return Double.valueOf(Double.POSITIVE_INFINITY); - } else if (c == 'N' && s.equals("NaN")) { - return Double.valueOf(Double.NaN); - } else if (c == '-' && s.charAt(1) == 'I' && (s.equals("-INF") || s.equals("-Infinity"))) { - return Double.valueOf(Double.NEGATIVE_INFINITY); - } - } - return new BigDecimal(s); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/ArithmeticExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/ArithmeticExpression.java b/src/main/java/org/apache/freemarker/core/ast/ArithmeticExpression.java deleted file mode 100644 index 3b75418..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/ArithmeticExpression.java +++ /dev/null @@ -1,129 +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.model.impl.SimpleNumber; - -/** - * An operator for arithmetic operations. Note that the + operator is in {@link AddConcatExpression}, because its - * overloaded (does string concatenation and more). - */ -final class ArithmeticExpression extends Expression { - - static final int TYPE_SUBSTRACTION = 0; - static final int TYPE_MULTIPLICATION = 1; - static final int TYPE_DIVISION = 2; - static final int TYPE_MODULO = 3; - - private static final char[] OPERATOR_IMAGES = new char[] { '-', '*', '/', '%' }; - - private final Expression lho; - private final Expression rho; - private final int operator; - - ArithmeticExpression(Expression lho, Expression rho, int operator) { - this.lho = lho; - this.rho = rho; - this.operator = operator; - } - - @Override - TemplateModel _eval(Environment env) throws TemplateException { - return _eval(env, this, lho.evalToNumber(env), operator, rho.evalToNumber(env)); - } - - static TemplateModel _eval(Environment env, TemplateObject parent, Number lhoNumber, int operator, Number rhoNumber) - throws TemplateException, _MiscTemplateException { - ArithmeticEngine ae = EvalUtil.getArithmeticEngine(env, parent); - switch (operator) { - case TYPE_SUBSTRACTION : - return new SimpleNumber(ae.subtract(lhoNumber, rhoNumber)); - case TYPE_MULTIPLICATION : - return new SimpleNumber(ae.multiply(lhoNumber, rhoNumber)); - case TYPE_DIVISION : - return new SimpleNumber(ae.divide(lhoNumber, rhoNumber)); - case TYPE_MODULO : - return new SimpleNumber(ae.modulus(lhoNumber, rhoNumber)); - default: - if (parent instanceof Expression) { - throw new _MiscTemplateException((Expression) parent, - "Unknown operation: ", Integer.valueOf(operator)); - } else { - throw new _MiscTemplateException("Unknown operation: ", Integer.valueOf(operator)); - } - } - } - - @Override - public String getCanonicalForm() { - return lho.getCanonicalForm() + ' ' + getOperatorSymbol(operator) + ' ' + rho.getCanonicalForm(); - } - - @Override - String getNodeTypeSymbol() { - return String.valueOf(getOperatorSymbol(operator)); - } - - static char getOperatorSymbol(int operator) { - return OPERATOR_IMAGES[operator]; - } - - @Override - boolean isLiteral() { - return constantValue != null || (lho.isLiteral() && rho.isLiteral()); - } - - @Override - protected Expression deepCloneWithIdentifierReplaced_inner( - String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) { - return new ArithmeticExpression( - lho.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState), - rho.deepCloneWithIdentifierReplaced(replacedIdentifier, replacement, replacementState), - operator); - } - - @Override - int getParameterCount() { - return 3; - } - - @Override - Object getParameterValue(int idx) { - switch (idx) { - case 0: return lho; - case 1: return rho; - case 2: return Integer.valueOf(operator); - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - ParameterRole getParameterRole(int idx) { - switch (idx) { - case 0: return ParameterRole.LEFT_HAND_OPERAND; - case 1: return ParameterRole.RIGHT_HAND_OPERAND; - case 2: return ParameterRole.AST_NODE_SUBTYPE; - default: throw new IndexOutOfBoundsException(); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/Assignment.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/Assignment.java b/src/main/java/org/apache/freemarker/core/ast/Assignment.java deleted file mode 100644 index bed2088..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/Assignment.java +++ /dev/null @@ -1,280 +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.ast.FMParserConstants; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateNumberModel; -import org.apache.freemarker.core.util._StringUtil; - -/** - * An instruction that makes a single assignment, like [#local x=1]. - * This is also used as the child of {@link AssignmentInstruction}, if there are multiple assignments in the same tag, - * like in [#local x=1 x=2]. - */ -final class Assignment extends TemplateElement { - - // These must not clash with ArithmeticExpression.TYPE_... constants: - private static final int OPERATOR_TYPE_EQUALS = 0x10000; - private static final int OPERATOR_TYPE_PLUS_EQUALS = 0x10001; - private static final int OPERATOR_TYPE_PLUS_PLUS = 0x10002; - private static final int OPERATOR_TYPE_MINUS_MINUS = 0x10003; - - private final int/*enum*/ scope; - private final String variableName; - private final int operatorType; - private final Expression valueExp; - private Expression namespaceExp; - - static final int NAMESPACE = 1; - static final int LOCAL = 2; - static final int GLOBAL = 3; - - private static final Number ONE = Integer.valueOf(1); - - /** - * @param variableName the variable name to assign to. - * @param valueExp the expression to assign. - * @param scope the scope of the assignment, one of NAMESPACE, LOCAL, or GLOBAL - */ - Assignment(String variableName, - int operator, - Expression valueExp, - int scope) { - this.scope = scope; - - this.variableName = variableName; - - if (operator == FMParserConstants.EQUALS) { - operatorType = OPERATOR_TYPE_EQUALS; - } else { - switch (operator) { - case FMParserConstants.PLUS_PLUS: - operatorType = OPERATOR_TYPE_PLUS_PLUS; - break; - case FMParserConstants.MINUS_MINUS: - operatorType = OPERATOR_TYPE_MINUS_MINUS; - break; - case FMParserConstants.PLUS_EQUALS: - operatorType = OPERATOR_TYPE_PLUS_EQUALS; - break; - case FMParserConstants.MINUS_EQUALS: - operatorType = ArithmeticExpression.TYPE_SUBSTRACTION; - break; - case FMParserConstants.TIMES_EQUALS: - operatorType = ArithmeticExpression.TYPE_MULTIPLICATION; - break; - case FMParserConstants.DIV_EQUALS: - operatorType = ArithmeticExpression.TYPE_DIVISION; - break; - case FMParserConstants.MOD_EQUALS: - operatorType = ArithmeticExpression.TYPE_MODULO; - break; - default: - throw new BugException(); - } - } - - this.valueExp = valueExp; - } - - void setNamespaceExp(Expression namespaceExp) { - if (scope != NAMESPACE && namespaceExp != null) throw new BugException(); - this.namespaceExp = namespaceExp; - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException { - final Environment.Namespace namespace; - if (namespaceExp == null) { - switch (scope) { - case LOCAL: - namespace = null; - break; - case GLOBAL: - namespace = env.getGlobalNamespace(); - break; - case NAMESPACE: - namespace = env.getCurrentNamespace(); - break; - default: - throw new BugException("Unexpected scope type: " + scope); - } - } else { - TemplateModel namespaceTM = namespaceExp.eval(env); - try { - namespace = (Environment.Namespace) namespaceTM; - } catch (ClassCastException e) { - throw new NonNamespaceException(namespaceExp, namespaceTM, env); - } - if (namespace == null) { - throw InvalidReferenceException.getInstance(namespaceExp, env); - } - } - - TemplateModel value; - if (operatorType == OPERATOR_TYPE_EQUALS) { - value = valueExp.eval(env); - valueExp.assertNonNull(value, env); - } else { - TemplateModel lhoValue; - if (namespace == null) { - lhoValue = env.getLocalVariable(variableName); - } else { - lhoValue = namespace.get(variableName); - } - - if (operatorType == OPERATOR_TYPE_PLUS_EQUALS) { // Add or concat operation - if (lhoValue == null) { - throw InvalidReferenceException.getInstance( - variableName, getOperatorTypeAsString(), env); - } - - value = valueExp.eval(env); - valueExp.assertNonNull(value, env); - value = AddConcatExpression._eval(env, namespaceExp, null, lhoValue, valueExp, value); - } else { // Numerical operation - Number lhoNumber; - if (lhoValue instanceof TemplateNumberModel) { - lhoNumber = EvalUtil.modelToNumber((TemplateNumberModel) lhoValue, null); - } else if (lhoValue == null) { - throw InvalidReferenceException.getInstance(variableName, getOperatorTypeAsString(), env); - } else { - throw new NonNumericalException(variableName, lhoValue, null, env); - } - - if (operatorType == OPERATOR_TYPE_PLUS_PLUS) { - value = AddConcatExpression._evalOnNumbers(env, getParentElement(), lhoNumber, ONE); - } else if (operatorType == OPERATOR_TYPE_MINUS_MINUS) { - value = ArithmeticExpression._eval( - env, getParentElement(), lhoNumber, ArithmeticExpression.TYPE_SUBSTRACTION, ONE); - } else { // operatorType == ArithmeticExpression.TYPE_... - Number rhoNumber = valueExp.evalToNumber(env); - value = ArithmeticExpression._eval(env, this, lhoNumber, operatorType, rhoNumber); - } - } - } - - if (namespace == null) { - env.setLocalVariable(variableName, value); - } else { - namespace.put(variableName, value); - } - return null; - } - - @Override - protected String dump(boolean canonical) { - StringBuilder buf = new StringBuilder(); - String dn = getParentElement() instanceof AssignmentInstruction ? null : getNodeTypeSymbol(); - if (dn != null) { - if (canonical) buf.append("<"); - buf.append(dn); - buf.append(' '); - } - - buf.append(_StringUtil.toFTLTopLevelTragetIdentifier(variableName)); - - if (valueExp != null) { - buf.append(' '); - } - buf.append(getOperatorTypeAsString()); - if (valueExp != null) { - buf.append(' '); - buf.append(valueExp.getCanonicalForm()); - } - if (dn != null) { - if (namespaceExp != null) { - buf.append(" in "); - buf.append(namespaceExp.getCanonicalForm()); - } - if (canonical) buf.append(">"); - } - String result = buf.toString(); - return result; - } - - @Override - String getNodeTypeSymbol() { - return getDirectiveName(scope); - } - - static String getDirectiveName(int scope) { - if (scope == Assignment.LOCAL) { - return "#local"; - } else if (scope == Assignment.GLOBAL) { - return "#global"; - } else if (scope == Assignment.NAMESPACE) { - return "#assign"; - } else { - return "#{unknown_assignment_type}"; - } - } - - @Override - int getParameterCount() { - return 5; - } - - @Override - Object getParameterValue(int idx) { - switch (idx) { - case 0: return variableName; - case 1: return getOperatorTypeAsString(); - case 2: return valueExp; - case 3: return Integer.valueOf(scope); - case 4: return namespaceExp; - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - ParameterRole getParameterRole(int idx) { - switch (idx) { - case 0: return ParameterRole.ASSIGNMENT_TARGET; - case 1: return ParameterRole.ASSIGNMENT_OPERATOR; - case 2: return ParameterRole.ASSIGNMENT_SOURCE; - case 3: return ParameterRole.VARIABLE_SCOPE; - case 4: return ParameterRole.NAMESPACE; - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - boolean isNestedBlockRepeater() { - return false; - } - - private String getOperatorTypeAsString() { - if (operatorType == OPERATOR_TYPE_EQUALS) { - return "="; - } else if (operatorType == OPERATOR_TYPE_PLUS_EQUALS) { - return "+="; - } else if (operatorType == OPERATOR_TYPE_PLUS_PLUS) { - return "++"; - } else if (operatorType == OPERATOR_TYPE_MINUS_MINUS) { - return "--"; - } else { - return ArithmeticExpression.getOperatorSymbol(operatorType) + "="; - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/AssignmentInstruction.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/AssignmentInstruction.java b/src/main/java/org/apache/freemarker/core/ast/AssignmentInstruction.java deleted file mode 100644 index caff0bb..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/AssignmentInstruction.java +++ /dev/null @@ -1,117 +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; - -/** - * An instruction that does multiple assignments, like [#local x=1 x=2]. - * Each assignment is represented by a {@link Assignment} child element. - * If there's only one assignment, its usually just a {@link Assignment} without parent {@link AssignmentInstruction}. - */ -final class AssignmentInstruction extends TemplateElement { - - private int scope; - private Expression namespaceExp; - - AssignmentInstruction(int scope) { - this.scope = scope; - setChildBufferCapacity(1); - } - - void addAssignment(Assignment assignment) { - addChild(assignment); - } - - void setNamespaceExp(Expression namespaceExp) { - this.namespaceExp = namespaceExp; - int ln = getChildCount(); - for (int i = 0; i < ln; i++) { - ((Assignment) getChild(i)).setNamespaceExp(namespaceExp); - } - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException, IOException { - return getChildBuffer(); - } - - @Override - protected String dump(boolean canonical) { - StringBuilder buf = new StringBuilder(); - if (canonical) buf.append('<'); - buf.append(Assignment.getDirectiveName(scope)); - if (canonical) { - buf.append(' '); - int ln = getChildCount(); - for (int i = 0; i < ln; i++) { - if (i != 0) { - buf.append(", "); - } - Assignment assignment = (Assignment) getChild(i); - buf.append(assignment.getCanonicalForm()); - } - } else { - buf.append("-container"); - } - if (namespaceExp != null) { - buf.append(" in "); - buf.append(namespaceExp.getCanonicalForm()); - } - if (canonical) buf.append(">"); - return buf.toString(); - } - - @Override - int getParameterCount() { - return 2; - } - - @Override - Object getParameterValue(int idx) { - switch (idx) { - case 0: return Integer.valueOf(scope); - case 1: return namespaceExp; - default: return null; - } - } - - @Override - ParameterRole getParameterRole(int idx) { - switch (idx) { - case 0: return ParameterRole.VARIABLE_SCOPE; - case 1: return ParameterRole.NAMESPACE; - default: return null; - } - } - - @Override - String getNodeTypeSymbol() { - return Assignment.getDirectiveName(scope); - } - - @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/AttemptBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/AttemptBlock.java b/src/main/java/org/apache/freemarker/core/ast/AttemptBlock.java deleted file mode 100644 index ee39820..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/AttemptBlock.java +++ /dev/null @@ -1,89 +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; - -/** - * Holder for the attempted section of the #attempt element and of the nested #recover element ({@link RecoveryBlock}). - */ -final class AttemptBlock extends TemplateElement { - - private TemplateElement attemptedSection; - private RecoveryBlock recoverySection; - - AttemptBlock(TemplateElements attemptedSectionChildren, RecoveryBlock recoverySection) { - TemplateElement attemptedSection = attemptedSectionChildren.asSingleElement(); - this.attemptedSection = attemptedSection; - this.recoverySection = recoverySection; - setChildBufferCapacity(2); - addChild(attemptedSection); // for backward compatibility - addChild(recoverySection); - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException, IOException { - env.visitAttemptRecover(this, attemptedSection, recoverySection); - return null; - } - - @Override - protected String dump(boolean canonical) { - if (!canonical) { - return getNodeTypeSymbol(); - } else { - StringBuilder buf = new StringBuilder(); - buf.append("<").append(getNodeTypeSymbol()).append(">"); - buf.append(getChildrenCanonicalForm()); - buf.append("</").append(getNodeTypeSymbol()).append(">"); - return buf.toString(); - } - } - - @Override - int getParameterCount() { - return 1; - } - - @Override - Object getParameterValue(int idx) { - if (idx != 0) throw new IndexOutOfBoundsException(); - return recoverySection; - } - - @Override - ParameterRole getParameterRole(int idx) { - if (idx != 0) throw new IndexOutOfBoundsException(); - return ParameterRole.ERROR_HANDLER; - } - - @Override - String getNodeTypeSymbol() { - return "#attempt"; - } - - @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/AutoEscBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/AutoEscBlock.java b/src/main/java/org/apache/freemarker/core/ast/AutoEscBlock.java deleted file mode 100644 index beb0bee..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/AutoEscBlock.java +++ /dev/null @@ -1,79 +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; - -/** - * An #autoEsc element - */ -final class AutoEscBlock extends TemplateElement { - - AutoEscBlock(TemplateElements children) { - setChildren(children); - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException, IOException { - return getChildBuffer(); - } - - @Override - protected String dump(boolean canonical) { - if (canonical) { - return "<" + getNodeTypeSymbol() + "\">" + getChildrenCanonicalForm() + "</" + getNodeTypeSymbol() + ">"; - } else { - return getNodeTypeSymbol(); - } - } - - @Override - String getNodeTypeSymbol() { - return "#autoesc"; - } - - @Override - int getParameterCount() { - return 0; - } - - @Override - Object getParameterValue(int idx) { - throw new IndexOutOfBoundsException(); - } - - @Override - ParameterRole getParameterRole(int idx) { - throw new IndexOutOfBoundsException(); - } - - @Override - boolean isIgnorable(boolean stripWhitespace) { - return getChildCount() == 0; - } - - @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/BackwardCompatibleTemplateNumberFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BackwardCompatibleTemplateNumberFormat.java b/src/main/java/org/apache/freemarker/core/ast/BackwardCompatibleTemplateNumberFormat.java deleted file mode 100644 index 448dc26..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BackwardCompatibleTemplateNumberFormat.java +++ /dev/null @@ -1,30 +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; - -/** - * Only exists for emulating pre-2.3.24-IcI {@code ?string} behavior. - * - * @since 2.3.24 - */ -abstract class BackwardCompatibleTemplateNumberFormat extends TemplateNumberFormat { - - abstract String format(Number number) throws UnformattableValueException; - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/BlockAssignment.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BlockAssignment.java b/src/main/java/org/apache/freemarker/core/ast/BlockAssignment.java deleted file mode 100644 index 20320c2..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BlockAssignment.java +++ /dev/null @@ -1,184 +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.StringWriter; -import java.io.Writer; -import java.util.Map; - -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.TemplateTransformModel; -import org.apache.freemarker.core.model.impl.SimpleScalar; - -/** - * Like [#local x]...[/#local]. - */ -final class BlockAssignment extends TemplateElement { - - private final String varName; - private final Expression namespaceExp; - private final int scope; - private final MarkupOutputFormat<?> markupOutputFormat; - - BlockAssignment(TemplateElements children, String varName, int scope, Expression namespaceExp, MarkupOutputFormat<?> markupOutputFormat) { - setChildren(children); - this.varName = varName; - this.namespaceExp = namespaceExp; - this.scope = scope; - this.markupOutputFormat = markupOutputFormat; - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException, IOException { - TemplateElement[] children = getChildBuffer(); - if (children != null) { - env.visitAndTransform(children, new CaptureOutput(env), null); - } else { - TemplateModel value = capturedStringToModel(""); - if (namespaceExp != null) { - Environment.Namespace ns = (Environment.Namespace) namespaceExp.eval(env); - ns.put(varName, value); - } else if (scope == Assignment.NAMESPACE) { - env.setVariable(varName, value); - } else if (scope == Assignment.GLOBAL) { - env.setGlobalVariable(varName, value); - } else if (scope == Assignment.LOCAL) { - env.setLocalVariable(varName, value); - } - } - return null; - } - - private TemplateModel capturedStringToModel(String s) throws TemplateModelException { - return markupOutputFormat == null ? new SimpleScalar(s) : markupOutputFormat.fromMarkup(s); - } - - private class CaptureOutput implements TemplateTransformModel { - private final Environment env; - private final Environment.Namespace fnsModel; - - CaptureOutput(Environment env) throws TemplateException { - this.env = env; - TemplateModel nsModel = null; - if (namespaceExp != null) { - nsModel = namespaceExp.eval(env); - if (!(nsModel instanceof Environment.Namespace)) { - throw new NonNamespaceException(namespaceExp, nsModel, env); - } - } - fnsModel = (Environment.Namespace ) nsModel; - } - - @Override - public Writer getWriter(Writer out, Map args) { - return new StringWriter() { - @Override - public void close() throws IOException { - TemplateModel result; - try { - result = capturedStringToModel(toString()); - } catch (TemplateModelException e) { - // [Java 1.6] e to cause - throw new IOException("Failed to create FTL value from captured string: " + e); - } - switch(scope) { - case Assignment.NAMESPACE: { - if (fnsModel != null) { - fnsModel.put(varName, result); - } else { - env.setVariable(varName, result); - } - break; - } - case Assignment.LOCAL: { - env.setLocalVariable(varName, result); - break; - } - case Assignment.GLOBAL: { - env.setGlobalVariable(varName, result); - break; - } - } - } - }; - } - } - - @Override - protected String dump(boolean canonical) { - StringBuilder sb = new StringBuilder(); - if (canonical) sb.append("<"); - sb.append(getNodeTypeSymbol()); - sb.append(' '); - sb.append(varName); - if (namespaceExp != null) { - sb.append(" in "); - sb.append(namespaceExp.getCanonicalForm()); - } - if (canonical) { - sb.append('>'); - sb.append(getChildrenCanonicalForm()); - sb.append("</"); - sb.append(getNodeTypeSymbol()); - sb.append('>'); - } else { - sb.append(" = .nested_output"); - } - return sb.toString(); - } - - @Override - String getNodeTypeSymbol() { - return Assignment.getDirectiveName(scope); - } - - @Override - int getParameterCount() { - return 3; - } - - @Override - Object getParameterValue(int idx) { - switch (idx) { - case 0: return varName; - case 1: return Integer.valueOf(scope); - case 2: return namespaceExp; - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - ParameterRole getParameterRole(int idx) { - switch (idx) { - case 0: return ParameterRole.ASSIGNMENT_TARGET; - case 1: return ParameterRole.VARIABLE_SCOPE; - case 2: return ParameterRole.NAMESPACE; - default: 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/BodyInstruction.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BodyInstruction.java b/src/main/java/org/apache/freemarker/core/ast/BodyInstruction.java deleted file mode 100644 index 548f9fd..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BodyInstruction.java +++ /dev/null @@ -1,160 +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.Collection; -import java.util.Collections; -import java.util.List; - -import org.apache.freemarker.core.TemplateException; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; - -/** - * An instruction that processes the nested block within a macro instruction. - */ -final class BodyInstruction extends TemplateElement { - - - private List bodyParameters; - - - BodyInstruction(List bodyParameters) { - this.bodyParameters = bodyParameters; - } - - List getBodyParameters() { - return bodyParameters; - } - - /** - * There is actually a subtle but essential point in the code below. - * A macro operates in the context in which it's defined. However, - * a nested block within a macro instruction is defined in the - * context in which the macro was invoked. So, we actually need to - * temporarily switch the namespace and macro context back to - * what it was before macro invocation to implement this properly. - * I (JR) realized this thanks to some incisive comments from Daniel Dekany. - */ - @Override - TemplateElement[] accept(Environment env) throws IOException, TemplateException { - Context bodyContext = new Context(env); - env.invokeNestedContent(bodyContext); - return null; - } - - @Override - protected String dump(boolean canonical) { - StringBuilder sb = new StringBuilder(); - if (canonical) sb.append('<'); - sb.append(getNodeTypeSymbol()); - if (bodyParameters != null) { - for (int i = 0; i < bodyParameters.size(); i++) { - sb.append(' '); - sb.append(((Expression) bodyParameters.get(i)).getCanonicalForm()); - } - } - if (canonical) sb.append('>'); - return sb.toString(); - } - - @Override - String getNodeTypeSymbol() { - return "#nested"; - } - - @Override - int getParameterCount() { - return bodyParameters != null ? bodyParameters.size() : 0; - } - - @Override - Object getParameterValue(int idx) { - checkIndex(idx); - return bodyParameters.get(idx); - } - - @Override - ParameterRole getParameterRole(int idx) { - checkIndex(idx); - return ParameterRole.PASSED_VALUE; - } - - private void checkIndex(int idx) { - if (bodyParameters == null || idx >= bodyParameters.size()) { - throw new IndexOutOfBoundsException(); - } - } - - /* - boolean heedsOpeningWhitespace() { - return true; - } - - boolean heedsTrailingWhitespace() { - return true; - } - */ - - @Override - boolean isShownInStackTrace() { - return true; - } - - class Context implements LocalContext { - Macro.Context invokingMacroContext; - Environment.Namespace bodyVars; - - Context(Environment env) throws TemplateException { - invokingMacroContext = env.getCurrentMacroContext(); - List bodyParameterNames = invokingMacroContext.nestedContentParameterNames; - if (bodyParameters != null) { - for (int i = 0; i < bodyParameters.size(); i++) { - Expression exp = (Expression) bodyParameters.get(i); - TemplateModel tm = exp.eval(env); - if (bodyParameterNames != null && i < bodyParameterNames.size()) { - String bodyParameterName = (String) bodyParameterNames.get(i); - if (bodyVars == null) { - bodyVars = env.new Namespace(); - } - bodyVars.put(bodyParameterName, tm); - } - } - } - } - - @Override - public TemplateModel getLocalVariable(String name) throws TemplateModelException { - return bodyVars == null ? null : bodyVars.get(name); - } - - @Override - public Collection getLocalVariableNames() { - List bodyParameterNames = invokingMacroContext.nestedContentParameterNames; - return bodyParameterNames == null ? Collections.EMPTY_LIST : bodyParameterNames; - } - } - - @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/BooleanExpression.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BooleanExpression.java b/src/main/java/org/apache/freemarker/core/ast/BooleanExpression.java deleted file mode 100644 index 08e1dc7..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BooleanExpression.java +++ /dev/null @@ -1,32 +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.TemplateBooleanModel; -import org.apache.freemarker.core.model.TemplateModel; - -abstract class BooleanExpression extends Expression { - - @Override - TemplateModel _eval(Environment env) throws TemplateException { - return evalToBoolean(env) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/BooleanLiteral.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BooleanLiteral.java b/src/main/java/org/apache/freemarker/core/ast/BooleanLiteral.java deleted file mode 100644 index 82cfb8f..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BooleanLiteral.java +++ /dev/null @@ -1,88 +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.model.TemplateBooleanModel; -import org.apache.freemarker.core.model.TemplateModel; - -final class BooleanLiteral extends Expression { - - private final boolean val; - - public BooleanLiteral(boolean val) { - this.val = val; - } - - static TemplateBooleanModel getTemplateModel(boolean b) { - return b? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } - - @Override - boolean evalToBoolean(Environment env) { - return val; - } - - @Override - public String getCanonicalForm() { - return val ? MiscUtil.C_TRUE : MiscUtil.C_FALSE; - } - - @Override - String getNodeTypeSymbol() { - return getCanonicalForm(); - } - - @Override - public String toString() { - return val ? MiscUtil.C_TRUE : MiscUtil.C_FALSE; - } - - @Override - TemplateModel _eval(Environment env) { - return val ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } - - @Override - boolean isLiteral() { - return true; - } - - @Override - protected Expression deepCloneWithIdentifierReplaced_inner( - String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) { - return new BooleanLiteral(val); - } - - @Override - int getParameterCount() { - return 0; - } - - @Override - Object getParameterValue(int idx) { - throw new IndexOutOfBoundsException(); - } - - @Override - ParameterRole getParameterRole(int idx) { - throw new IndexOutOfBoundsException(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/BoundedRangeModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BoundedRangeModel.java b/src/main/java/org/apache/freemarker/core/ast/BoundedRangeModel.java deleted file mode 100644 index 88c1d0b..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BoundedRangeModel.java +++ /dev/null @@ -1,70 +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; - - -/** - * A range between two integers (maybe 0 long). - */ -final class BoundedRangeModel extends RangeModel { - - private final int step, size; - private final boolean rightAdaptive; - private final boolean affectedByStringSlicingBug; - - /** - * @param inclusiveEnd Tells if the {@code end} index is part of the range. - * @param rightAdaptive Tells if the right end of the range adapts to the size of the sliced value, if otherwise - * it would be bigger than that. - */ - BoundedRangeModel(int begin, int end, boolean inclusiveEnd, boolean rightAdaptive) { - super(begin); - step = begin <= end ? 1 : -1; - size = Math.abs(end - begin) + (inclusiveEnd ? 1 : 0); - this.rightAdaptive = rightAdaptive; - affectedByStringSlicingBug = inclusiveEnd; - } - - @Override - public int size() { - return size; - } - - @Override - int getStep() { - return step; - } - - @Override - boolean isRightUnbounded() { - return false; - } - - @Override - boolean isRightAdaptive() { - return rightAdaptive; - } - - @Override - boolean isAffactedByStringSlicingBug() { - return affectedByStringSlicingBug; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/BreakInstruction.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BreakInstruction.java b/src/main/java/org/apache/freemarker/core/ast/BreakInstruction.java deleted file mode 100644 index 67a770e..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BreakInstruction.java +++ /dev/null @@ -1,70 +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; - -/** - * Represents a <break> instruction to break out of a loop. - */ -final class BreakInstruction extends TemplateElement { - - @Override - TemplateElement[] accept(Environment env) { - throw Break.INSTANCE; - } - - @Override - protected String dump(boolean canonical) { - return canonical ? "<" + getNodeTypeSymbol() + "/>" : getNodeTypeSymbol(); - } - - @Override - String getNodeTypeSymbol() { - return "#break"; - } - - @Override - int getParameterCount() { - return 0; - } - - @Override - Object getParameterValue(int idx) { - throw new IndexOutOfBoundsException(); - } - - @Override - ParameterRole getParameterRole(int idx) { - throw new IndexOutOfBoundsException(); - } - - static class Break extends RuntimeException { - static final Break INSTANCE = new Break(); - private Break() { - } - } - - @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/BugException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BugException.java b/src/main/java/org/apache/freemarker/core/ast/BugException.java deleted file mode 100644 index 9850b74..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BugException.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; - -/** - * An unexpected state was reached that is certainly caused by a bug in FreeMarker. - * - * @since 2.3.21 - */ -public class BugException extends RuntimeException { - - private static final String COMMON_MESSAGE - = "A bug was detected in FreeMarker; please report it with stack-trace"; - - public BugException() { - this((Throwable) null); - } - - public BugException(String message) { - this(message, null); - } - - public BugException(Throwable cause) { - super(COMMON_MESSAGE, cause); - } - - public BugException(String message, Throwable cause) { - super(COMMON_MESSAGE + ": " + message, cause); - } - - public BugException(int value) { - this(String.valueOf(value)); - } - -}