http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/BuiltInsForSequences.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForSequences.java b/src/main/java/org/apache/freemarker/core/ast/BuiltInsForSequences.java deleted file mode 100644 index f0b299b..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForSequences.java +++ /dev/null @@ -1,877 +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.Serializable; -import java.text.Collator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -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.TemplateDateModel; -import org.apache.freemarker.core.model.TemplateHashModel; -import org.apache.freemarker.core.model.TemplateMethodModelEx; -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.TemplateNumberModel; -import org.apache.freemarker.core.model.TemplateScalarModel; -import org.apache.freemarker.core.model.TemplateSequenceModel; -import org.apache.freemarker.core.model.impl.SimpleNumber; -import org.apache.freemarker.core.model.impl.SimpleScalar; -import org.apache.freemarker.core.model.impl.TemplateModelListSequence; -import org.apache.freemarker.core.model.impl.beans.CollectionModel; -import org.apache.freemarker.core.model.Constants; -import org.apache.freemarker.core.util._StringUtil; - -/** - * A holder for builtins that operate exclusively on sequence or collection left-hand value. - */ -class BuiltInsForSequences { - - static class chunkBI extends BuiltInForSequence { - - private class BIMethod implements TemplateMethodModelEx { - - private final TemplateSequenceModel tsm; - - private BIMethod(TemplateSequenceModel tsm) { - this.tsm = tsm; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1, 2); - int chunkSize = getNumberMethodArg(args, 0).intValue(); - - return new ChunkedSequence( - tsm, - chunkSize, - args.size() > 1 ? (TemplateModel) args.get(1) : null); - } - } - - private static class ChunkedSequence implements TemplateSequenceModel { - - private final TemplateSequenceModel wrappedTsm; - - private final int chunkSize; - - private final TemplateModel fillerItem; - - private final int numberOfChunks; - - private ChunkedSequence( - TemplateSequenceModel wrappedTsm, int chunkSize, TemplateModel fillerItem) - throws TemplateModelException { - if (chunkSize < 1) { - throw new _TemplateModelException("The 1st argument to ?', key, ' (...) must be at least 1."); - } - this.wrappedTsm = wrappedTsm; - this.chunkSize = chunkSize; - this.fillerItem = fillerItem; - numberOfChunks = (wrappedTsm.size() + chunkSize - 1) / chunkSize; - } - - @Override - public TemplateModel get(final int chunkIndex) - throws TemplateModelException { - if (chunkIndex >= numberOfChunks) { - return null; - } - - return new TemplateSequenceModel() { - - private final int baseIndex = chunkIndex * chunkSize; - - @Override - public TemplateModel get(int relIndex) - throws TemplateModelException { - int absIndex = baseIndex + relIndex; - if (absIndex < wrappedTsm.size()) { - return wrappedTsm.get(absIndex); - } else { - return absIndex < numberOfChunks * chunkSize - ? fillerItem - : null; - } - } - - @Override - public int size() throws TemplateModelException { - return fillerItem != null || chunkIndex + 1 < numberOfChunks - ? chunkSize - : wrappedTsm.size() - baseIndex; - } - - }; - } - - @Override - public int size() throws TemplateModelException { - return numberOfChunks; - } - - } - - @Override - TemplateModel calculateResult(TemplateSequenceModel tsm) throws TemplateModelException { - return new BIMethod(tsm); - } - - } - - static class firstBI extends BuiltIn { - - @Override - TemplateModel _eval(Environment env) - throws TemplateException { - TemplateModel model = target.eval(env); - // In 2.3.x only, we prefer TemplateSequenceModel for - // backward compatibility. In 2.4.x, we prefer TemplateCollectionModel. - if (model instanceof TemplateSequenceModel && !isBuggySeqButGoodCollection(model)) { - return calculateResultForSequence((TemplateSequenceModel) model); - } else if (model instanceof TemplateCollectionModel) { - return calculateResultForColletion((TemplateCollectionModel) model); - } else { - throw new NonSequenceOrCollectionException(target, model, env); - } - } - - private TemplateModel calculateResultForSequence(TemplateSequenceModel seq) - throws TemplateModelException { - if (seq.size() == 0) { - return null; - } - return seq.get(0); - } - - private TemplateModel calculateResultForColletion(TemplateCollectionModel coll) - throws TemplateModelException { - TemplateModelIterator iter = coll.iterator(); - if (!iter.hasNext()) { - return null; - } - return iter.next(); - } - - } - - static class joinBI extends BuiltIn { - - private class BIMethodForCollection implements TemplateMethodModelEx { - - private final Environment env; - private final TemplateCollectionModel coll; - - private BIMethodForCollection(Environment env, TemplateCollectionModel coll) { - this.env = env; - this.coll = coll; - } - - @Override - public Object exec(List args) - throws TemplateModelException { - checkMethodArgCount(args, 1, 3); - final String separator = getStringMethodArg(args, 0); - final String whenEmpty = getOptStringMethodArg(args, 1); - final String afterLast = getOptStringMethodArg(args, 2); - - StringBuilder sb = new StringBuilder(); - - TemplateModelIterator it = coll.iterator(); - - int idx = 0; - boolean hadItem = false; - while (it.hasNext()) { - TemplateModel item = it.next(); - if (item != null) { - if (hadItem) { - sb.append(separator); - } else { - hadItem = true; - } - try { - sb.append(EvalUtil.coerceModelToStringOrUnsupportedMarkup(item, null, null, env)); - } catch (TemplateException e) { - throw new _TemplateModelException(e, - "\"?", key, "\" failed at index ", Integer.valueOf(idx), " with this error:\n\n", - MessageUtil.EMBEDDED_MESSAGE_BEGIN, - new _DelayedGetMessageWithoutStackTop(e), - MessageUtil.EMBEDDED_MESSAGE_END); - } - } - idx++; - } - if (hadItem) { - if (afterLast != null) sb.append(afterLast); - } else { - if (whenEmpty != null) sb.append(whenEmpty); - } - return new SimpleScalar(sb.toString()); - } - - } - - @Override - TemplateModel _eval(Environment env) throws TemplateException { - TemplateModel model = target.eval(env); - if (model instanceof TemplateCollectionModel) { - if (model instanceof RightUnboundedRangeModel) { - throw new _TemplateModelException( - "The sequence to join was right-unbounded numerical range, thus it's infinitely long."); - } - return new BIMethodForCollection(env, (TemplateCollectionModel) model); - } else if (model instanceof TemplateSequenceModel) { - return new BIMethodForCollection(env, new CollectionAndSequence((TemplateSequenceModel) model)); - } else { - throw new NonSequenceOrCollectionException(target, model, env); - } - } - - } - - static class lastBI extends BuiltInForSequence { - @Override - TemplateModel calculateResult(TemplateSequenceModel tsm) - throws TemplateModelException { - if (tsm.size() == 0) { - return null; - } - return tsm.get(tsm.size() - 1); - } - } - - static class reverseBI extends BuiltInForSequence { - private static class ReverseSequence implements TemplateSequenceModel { - private final TemplateSequenceModel seq; - - ReverseSequence(TemplateSequenceModel seq) { - this.seq = seq; - } - - @Override - public TemplateModel get(int index) throws TemplateModelException { - return seq.get(seq.size() - 1 - index); - } - - @Override - public int size() throws TemplateModelException { - return seq.size(); - } - } - - @Override - TemplateModel calculateResult(TemplateSequenceModel tsm) { - if (tsm instanceof ReverseSequence) { - return ((ReverseSequence) tsm).seq; - } else { - return new ReverseSequence(tsm); - } - } - } - - static class seq_containsBI extends BuiltIn { - private class BIMethodForCollection implements TemplateMethodModelEx { - private TemplateCollectionModel m_coll; - private Environment m_env; - - private BIMethodForCollection(TemplateCollectionModel coll, Environment env) { - m_coll = coll; - m_env = env; - } - - @Override - public Object exec(List args) - throws TemplateModelException { - checkMethodArgCount(args, 1); - TemplateModel arg = (TemplateModel) args.get(0); - TemplateModelIterator it = m_coll.iterator(); - int idx = 0; - while (it.hasNext()) { - if (modelsEqual(idx, it.next(), arg, m_env)) - return TemplateBooleanModel.TRUE; - idx++; - } - return TemplateBooleanModel.FALSE; - } - - } - - private class BIMethodForSequence implements TemplateMethodModelEx { - private TemplateSequenceModel m_seq; - private Environment m_env; - - private BIMethodForSequence(TemplateSequenceModel seq, Environment env) { - m_seq = seq; - m_env = env; - } - - @Override - public Object exec(List args) - throws TemplateModelException { - checkMethodArgCount(args, 1); - TemplateModel arg = (TemplateModel) args.get(0); - int size = m_seq.size(); - for (int i = 0; i < size; i++) { - if (modelsEqual(i, m_seq.get(i), arg, m_env)) - return TemplateBooleanModel.TRUE; - } - return TemplateBooleanModel.FALSE; - } - - } - - @Override - TemplateModel _eval(Environment env) - throws TemplateException { - TemplateModel model = target.eval(env); - // In 2.3.x only, we prefer TemplateSequenceModel for - // backward compatibility. In 2.4.x, we prefer TemplateCollectionModel. - if (model instanceof TemplateSequenceModel && !isBuggySeqButGoodCollection(model)) { - return new BIMethodForSequence((TemplateSequenceModel) model, env); - } else if (model instanceof TemplateCollectionModel) { - return new BIMethodForCollection((TemplateCollectionModel) model, env); - } else { - throw new NonSequenceOrCollectionException(target, model, env); - } - } - - } - - static class seq_index_ofBI extends BuiltIn { - - private class BIMethod implements TemplateMethodModelEx { - - protected final TemplateSequenceModel m_seq; - protected final TemplateCollectionModel m_col; - protected final Environment m_env; - - private BIMethod(Environment env) - throws TemplateException { - TemplateModel model = target.eval(env); - m_seq = model instanceof TemplateSequenceModel - && !isBuggySeqButGoodCollection(model) - ? (TemplateSequenceModel) model - : null; - // In 2.3.x only, we deny the possibility of collection - // access if there's sequence access. This is so to minimize - // the change of compatibility issues; without this, objects - // that implement both the sequence and collection interfaces - // would suddenly start using the collection interface, and if - // that's buggy that would surface now, breaking the application - // that despite its bugs has worked earlier. - m_col = m_seq == null && model instanceof TemplateCollectionModel - ? (TemplateCollectionModel) model - : null; - if (m_seq == null && m_col == null) { - throw new NonSequenceOrCollectionException(target, model, env); - } - - m_env = env; - } - - @Override - public final Object exec(List args) - throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - - TemplateModel target = (TemplateModel) args.get(0); - int foundAtIdx; - if (argCnt > 1) { - int startIndex = getNumberMethodArg(args, 1).intValue(); - // In 2.3.x only, we prefer TemplateSequenceModel for - // backward compatibility: - foundAtIdx = m_seq != null - ? findInSeq(target, startIndex) - : findInCol(target, startIndex); - } else { - // In 2.3.x only, we prefer TemplateSequenceModel for - // backward compatibility: - foundAtIdx = m_seq != null - ? findInSeq(target) - : findInCol(target); - } - return foundAtIdx == -1 ? Constants.MINUS_ONE : new SimpleNumber(foundAtIdx); - } - - int findInCol(TemplateModel target) throws TemplateModelException { - return findInCol(target, 0, Integer.MAX_VALUE); - } - - protected int findInCol(TemplateModel target, int startIndex) - throws TemplateModelException { - if (m_dir == 1) { - return findInCol(target, startIndex, Integer.MAX_VALUE); - } else { - return findInCol(target, 0, startIndex); - } - } - - protected int findInCol(TemplateModel target, - final int allowedRangeStart, final int allowedRangeEnd) - throws TemplateModelException { - if (allowedRangeEnd < 0) return -1; - - TemplateModelIterator it = m_col.iterator(); - - int foundAtIdx = -1; // -1 is the return value for "not found" - int idx = 0; - searchItem: while (it.hasNext()) { - if (idx > allowedRangeEnd) break searchItem; - - TemplateModel current = it.next(); - if (idx >= allowedRangeStart) { - if (modelsEqual(idx, current, target, m_env)) { - foundAtIdx = idx; - if (m_dir == 1) break searchItem; // "find first" - // Otherwise it's "find last". - } - } - idx++; - } - return foundAtIdx; - } - - int findInSeq(TemplateModel target) - throws TemplateModelException { - final int seqSize = m_seq.size(); - final int actualStartIndex; - - if (m_dir == 1) { - actualStartIndex = 0; - } else { - actualStartIndex = seqSize - 1; - } - - return findInSeq(target, actualStartIndex, seqSize); - } - - private int findInSeq(TemplateModel target, int startIndex) - throws TemplateModelException { - int seqSize = m_seq.size(); - - if (m_dir == 1) { - if (startIndex >= seqSize) { - return -1; - } - if (startIndex < 0) { - startIndex = 0; - } - } else { - if (startIndex >= seqSize) { - startIndex = seqSize - 1; - } - if (startIndex < 0) { - return -1; - } - } - - return findInSeq(target, startIndex, seqSize); - } - - private int findInSeq( - TemplateModel target, int scanStartIndex, int seqSize) - throws TemplateModelException { - if (m_dir == 1) { - for (int i = scanStartIndex; i < seqSize; i++) { - if (modelsEqual(i, m_seq.get(i), target, m_env)) return i; - } - } else { - for (int i = scanStartIndex; i >= 0; i--) { - if (modelsEqual(i, m_seq.get(i), target, m_env)) return i; - } - } - return -1; - } - - } - - private int m_dir; - - seq_index_ofBI(int dir) { - m_dir = dir; - } - - @Override - TemplateModel _eval(Environment env) - throws TemplateException { - return new BIMethod(env); - } - } - - static class sort_byBI extends sortBI { - class BIMethod implements TemplateMethodModelEx { - TemplateSequenceModel seq; - - BIMethod(TemplateSequenceModel seq) { - this.seq = seq; - } - - @Override - public Object exec(List args) - throws TemplateModelException { - // Should be: - // checkMethodArgCount(args, 1); - // But for BC: - if (args.size() < 1) throw MessageUtil.newArgCntError("?" + key, args.size(), 1); - - String[] subvars; - Object obj = args.get(0); - if (obj instanceof TemplateScalarModel) { - subvars = new String[]{((TemplateScalarModel) obj).getAsString()}; - } else if (obj instanceof TemplateSequenceModel) { - TemplateSequenceModel seq = (TemplateSequenceModel) obj; - int ln = seq.size(); - subvars = new String[ln]; - for (int i = 0; i < ln; i++) { - Object item = seq.get(i); - try { - subvars[i] = ((TemplateScalarModel) item) - .getAsString(); - } catch (ClassCastException e) { - if (!(item instanceof TemplateScalarModel)) { - throw new _TemplateModelException( - "The argument to ?", key, "(key), when it's a sequence, must be a " - + "sequence of strings, but the item at index ", Integer.valueOf(i), - " is not a string."); - } - } - } - } else { - throw new _TemplateModelException( - "The argument to ?", key, "(key) must be a string (the name of the subvariable), or a " - + "sequence of strings (the \"path\" to the subvariable)."); - } - return sort(seq, subvars); - } - } - - @Override - TemplateModel calculateResult(TemplateSequenceModel seq) { - return new BIMethod(seq); - } - } - - static class sortBI extends BuiltInForSequence { - - private static class BooleanKVPComparator implements Comparator, Serializable { - - @Override - public int compare(Object arg0, Object arg1) { - // JDK 1.2 doesn't have Boolean.compareTo - boolean b0 = ((Boolean) ((KVP) arg0).key).booleanValue(); - boolean b1 = ((Boolean) ((KVP) arg1).key).booleanValue(); - if (b0) { - return b1 ? 0 : 1; - } else { - return b1 ? -1 : 0; - } - } - } - private static class DateKVPComparator implements Comparator, Serializable { - - @Override - public int compare(Object arg0, Object arg1) { - return ((Date) ((KVP) arg0).key).compareTo( - (Date) ((KVP) arg1).key); - } - } - /** - * Stores a key-value pair. - */ - private static class KVP { - private Object key; - - private Object value; - private KVP(Object key, Object value) { - this.key = key; - this.value = value; - } - } - private static class LexicalKVPComparator implements Comparator { - private Collator collator; - - LexicalKVPComparator(Collator collator) { - this.collator = collator; - } - - @Override - public int compare(Object arg0, Object arg1) { - return collator.compare( - ((KVP) arg0).key, ((KVP) arg1).key); - } - } - private static class NumericalKVPComparator implements Comparator { - private ArithmeticEngine ae; - - private NumericalKVPComparator(ArithmeticEngine ae) { - this.ae = ae; - } - - @Override - public int compare(Object arg0, Object arg1) { - try { - return ae.compareNumbers( - (Number) ((KVP) arg0).key, - (Number) ((KVP) arg1).key); - } catch (TemplateException e) { - throw new ClassCastException( - "Failed to compare numbers: " + e); - } - } - } - - static TemplateModelException newInconsistentSortKeyTypeException( - int keyNamesLn, String firstType, String firstTypePlural, int index, TemplateModel key) { - String valueInMsg; - String valuesInMsg; - if (keyNamesLn == 0) { - valueInMsg = "value"; - valuesInMsg = "values"; - } else { - valueInMsg = "key value"; - valuesInMsg = "key values"; - } - return new _TemplateModelException( - startErrorMessage(keyNamesLn, index), - "All ", valuesInMsg, " in the sequence must be ", - firstTypePlural, ", because the first ", valueInMsg, - " was that. However, the ", valueInMsg, - " of the current item isn't a ", firstType, " but a ", - new _DelayedFTLTypeDescription(key), "."); - } - - /** - * Sorts a sequence for the <tt>sort</tt> and <tt>sort_by</tt> - * built-ins. - * - * @param seq the sequence to sort. - * @param keyNames the name of the subvariable whose value is used for the - * sorting. If the sorting is done by a sub-subvaruable, then this - * will be of length 2, and so on. If the sorting is done by the - * sequene items directly, then this argument has to be 0 length - * array or <code>null</code>. - * @return a new sorted sequence, or the original sequence if the - * sequence length was 0. - */ - static TemplateSequenceModel sort(TemplateSequenceModel seq, String[] keyNames) - throws TemplateModelException { - int ln = seq.size(); - if (ln == 0) return seq; - - ArrayList res = new ArrayList(ln); - - int keyNamesLn = keyNames == null ? 0 : keyNames.length; - - // Copy the Seq into a Java List[KVP] (also detects key type at the 1st item): - int keyType = KEY_TYPE_NOT_YET_DETECTED; - Comparator keyComparator = null; - for (int i = 0; i < ln; i++) { - final TemplateModel item = seq.get(i); - TemplateModel key = item; - for (int keyNameI = 0; keyNameI < keyNamesLn; keyNameI++) { - try { - key = ((TemplateHashModel) key).get(keyNames[keyNameI]); - } catch (ClassCastException e) { - if (!(key instanceof TemplateHashModel)) { - throw new _TemplateModelException( - startErrorMessage(keyNamesLn, i), - (keyNameI == 0 - ? "Sequence items must be hashes when using ?sort_by. " - : "The " + _StringUtil.jQuote(keyNames[keyNameI - 1])), - " subvariable is not a hash, so ?sort_by ", - "can't proceed with getting the ", - new _DelayedJQuote(keyNames[keyNameI]), - " subvariable."); - } else { - throw e; - } - } - if (key == null) { - throw new _TemplateModelException( - startErrorMessage(keyNamesLn, i), - "The " + _StringUtil.jQuote(keyNames[keyNameI]), " subvariable was not found."); - } - } // for each key - - if (keyType == KEY_TYPE_NOT_YET_DETECTED) { - if (key instanceof TemplateScalarModel) { - keyType = KEY_TYPE_STRING; - keyComparator = new LexicalKVPComparator( - Environment.getCurrentEnvironment().getCollator()); - } else if (key instanceof TemplateNumberModel) { - keyType = KEY_TYPE_NUMBER; - keyComparator = new NumericalKVPComparator( - Environment.getCurrentEnvironment() - .getArithmeticEngine()); - } else if (key instanceof TemplateDateModel) { - keyType = KEY_TYPE_DATE; - keyComparator = new DateKVPComparator(); - } else if (key instanceof TemplateBooleanModel) { - keyType = KEY_TYPE_BOOLEAN; - keyComparator = new BooleanKVPComparator(); - } else { - throw new _TemplateModelException( - startErrorMessage(keyNamesLn, i), - "Values used for sorting must be numbers, strings, date/times or booleans."); - } - } - switch(keyType) { - case KEY_TYPE_STRING: - try { - res.add(new KVP( - ((TemplateScalarModel) key).getAsString(), - item)); - } catch (ClassCastException e) { - if (!(key instanceof TemplateScalarModel)) { - throw newInconsistentSortKeyTypeException( - keyNamesLn, "string", "strings", i, key); - } else { - throw e; - } - } - break; - - case KEY_TYPE_NUMBER: - try { - res.add(new KVP( - ((TemplateNumberModel) key).getAsNumber(), - item)); - } catch (ClassCastException e) { - if (!(key instanceof TemplateNumberModel)) { - throw newInconsistentSortKeyTypeException( - keyNamesLn, "number", "numbers", i, key); - } - } - break; - - case KEY_TYPE_DATE: - try { - res.add(new KVP( - ((TemplateDateModel) key).getAsDate(), - item)); - } catch (ClassCastException e) { - if (!(key instanceof TemplateDateModel)) { - throw newInconsistentSortKeyTypeException( - keyNamesLn, "date/time", "date/times", i, key); - } - } - break; - - case KEY_TYPE_BOOLEAN: - try { - res.add(new KVP( - Boolean.valueOf(((TemplateBooleanModel) key).getAsBoolean()), - item)); - } catch (ClassCastException e) { - if (!(key instanceof TemplateBooleanModel)) { - throw newInconsistentSortKeyTypeException( - keyNamesLn, "boolean", "booleans", i, key); - } - } - break; - - default: - throw new BugException("Unexpected key type"); - } - } - - // Sort tje List[KVP]: - try { - Collections.sort(res, keyComparator); - } catch (Exception exc) { - throw new _TemplateModelException(exc, - startErrorMessage(keyNamesLn), "Unexpected error while sorting:" + exc); - } - - // Convert the List[KVP] to List[V]: - for (int i = 0; i < ln; i++) { - res.set(i, ((KVP) res.get(i)).value); - } - - return new TemplateModelListSequence(res); - } - - static Object[] startErrorMessage(int keyNamesLn) { - return new Object[] { (keyNamesLn == 0 ? "?sort" : "?sort_by(...)"), " failed: " }; - } - - static Object[] startErrorMessage(int keyNamesLn, int index) { - return new Object[] { - (keyNamesLn == 0 ? "?sort" : "?sort_by(...)"), - " failed at sequence index ", Integer.valueOf(index), - (index == 0 ? ": " : " (0-based): ") }; - } - - static final int KEY_TYPE_NOT_YET_DETECTED = 0; - - static final int KEY_TYPE_STRING = 1; - - static final int KEY_TYPE_NUMBER = 2; - - static final int KEY_TYPE_DATE = 3; - - static final int KEY_TYPE_BOOLEAN = 4; - - @Override - TemplateModel calculateResult(TemplateSequenceModel seq) - throws TemplateModelException { - return sort(seq, null); - } - - } - - private static boolean isBuggySeqButGoodCollection( - TemplateModel model) { - return model instanceof CollectionModel - ? !((CollectionModel) model).getSupportsIndexedAccess() - : false; - } - - private static boolean modelsEqual( - int seqItemIndex, TemplateModel seqItem, TemplateModel searchedItem, - Environment env) - throws TemplateModelException { - try { - return EvalUtil.compare( - seqItem, null, - EvalUtil.CMP_OP_EQUALS, null, - searchedItem, null, - null, false, - true, true, true, // The last one is true to emulate an old bug for BC - env); - } catch (TemplateException ex) { - throw new _TemplateModelException(ex, - "This error has occurred when comparing sequence item at 0-based index ", Integer.valueOf(seqItemIndex), - " to the searched item:\n", new _DelayedGetMessage(ex)); - } - } - - // Can't be instantiated - private BuiltInsForSequences() { } - -} \ 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/BuiltInsForStringsBasic.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsBasic.java b/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsBasic.java deleted file mode 100644 index 7c04050..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsBasic.java +++ /dev/null @@ -1,699 +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.List; -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.freemarker.core.TemplateException; -import org.apache.freemarker.core.model.TemplateBooleanModel; -import org.apache.freemarker.core.model.TemplateMethodModel; -import org.apache.freemarker.core.model.TemplateMethodModelEx; -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.impl.SimpleNumber; -import org.apache.freemarker.core.model.impl.SimpleScalar; -import org.apache.freemarker.core.model.impl.SimpleSequence; -import org.apache.freemarker.core.model.impl._StaticObjectWrappers; -import org.apache.freemarker.core.util._StringUtil; - -class BuiltInsForStringsBasic { - - static class cap_firstBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - int i = 0; - int ln = s.length(); - while (i < ln && Character.isWhitespace(s.charAt(i))) { - i++; - } - if (i < ln) { - StringBuilder b = new StringBuilder(s); - b.setCharAt(i, Character.toUpperCase(s.charAt(i))); - s = b.toString(); - } - return new SimpleScalar(s); - } - } - - static class capitalizeBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.capitalize(s)); - } - } - - static class chop_linebreakBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.chomp(s)); - } - } - - static class containsBI extends BuiltIn { - - private class BIMethod implements TemplateMethodModelEx { - - private final String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1); - return s.indexOf(getStringMethodArg(args, 0)) != -1 - ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } - } - - @Override - TemplateModel _eval(Environment env) throws TemplateException { - return new BIMethod(target.evalAndCoerceToStringOrUnsupportedMarkup(env, - "For sequences/collections (lists and such) use \"?seq_contains\" instead.")); - } - } - - static class ends_withBI extends BuiltInForString { - - private class BIMethod implements TemplateMethodModelEx { - private String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1); - return s.endsWith(getStringMethodArg(args, 0)) ? - TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new BIMethod(s); - } - } - - static class ensure_ends_withBI extends BuiltInForString { - - private class BIMethod implements TemplateMethodModelEx { - private String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1); - String suffix = getStringMethodArg(args, 0); - return new SimpleScalar(s.endsWith(suffix) ? s : s + suffix); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new BIMethod(s); - } - } - - static class ensure_starts_withBI extends BuiltInForString { - - private class BIMethod implements TemplateMethodModelEx { - private String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1, 3); - - final String checkedPrefix = getStringMethodArg(args, 0); - - final boolean startsWithPrefix; - final String addedPrefix; - if (args.size() > 1) { - addedPrefix = getStringMethodArg(args, 1); - long flags = args.size() > 2 - ? RegexpHelper.parseFlagString(getStringMethodArg(args, 2)) - : RegexpHelper.RE_FLAG_REGEXP; - - if ((flags & RegexpHelper.RE_FLAG_REGEXP) == 0) { - RegexpHelper.checkOnlyHasNonRegexpFlags(key, flags, true); - if ((flags & RegexpHelper.RE_FLAG_CASE_INSENSITIVE) == 0) { - startsWithPrefix = s.startsWith(checkedPrefix); - } else { - startsWithPrefix = s.toLowerCase().startsWith(checkedPrefix.toLowerCase()); - } - } else { - Pattern pattern = RegexpHelper.getPattern(checkedPrefix, (int) flags); - final Matcher matcher = pattern.matcher(s); - startsWithPrefix = matcher.lookingAt(); - } - } else { - startsWithPrefix = s.startsWith(checkedPrefix); - addedPrefix = checkedPrefix; - } - return new SimpleScalar(startsWithPrefix ? s : addedPrefix + s); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new BIMethod(s); - } - } - - static class index_ofBI extends BuiltIn { - - private class BIMethod implements TemplateMethodModelEx { - - private final String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - String subStr = getStringMethodArg(args, 0); - if (argCnt > 1) { - int startIdx = getNumberMethodArg(args, 1).intValue(); - return new SimpleNumber(findLast ? s.lastIndexOf(subStr, startIdx) : s.indexOf(subStr, startIdx)); - } else { - return new SimpleNumber(findLast ? s.lastIndexOf(subStr) : s.indexOf(subStr)); - } - } - } - - private final boolean findLast; - - index_ofBI(boolean findLast) { - this.findLast = findLast; - } - - @Override - TemplateModel _eval(Environment env) throws TemplateException { - return new BIMethod(target.evalAndCoerceToStringOrUnsupportedMarkup(env, - "For sequences/collections (lists and such) use \"?seq_index_of\" instead.")); - } - } - - static class keep_afterBI extends BuiltInForString { - class KeepAfterMethod implements TemplateMethodModelEx { - private String s; - - KeepAfterMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - String separatorString = getStringMethodArg(args, 0); - long flags = argCnt > 1 ? RegexpHelper.parseFlagString(getStringMethodArg(args, 1)) : 0; - - int startIndex; - if ((flags & RegexpHelper.RE_FLAG_REGEXP) == 0) { - RegexpHelper.checkOnlyHasNonRegexpFlags(key, flags, true); - if ((flags & RegexpHelper.RE_FLAG_CASE_INSENSITIVE) == 0) { - startIndex = s.indexOf(separatorString); - } else { - startIndex = s.toLowerCase().indexOf(separatorString.toLowerCase()); - } - if (startIndex >= 0) { - startIndex += separatorString.length(); - } - } else { - Pattern pattern = RegexpHelper.getPattern(separatorString, (int) flags); - final Matcher matcher = pattern.matcher(s); - if (matcher.find()) { - startIndex = matcher.end(); - } else { - startIndex = -1; - } - } - return startIndex == -1 ? TemplateScalarModel.EMPTY_STRING : new SimpleScalar(s.substring(startIndex)); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateModelException { - return new KeepAfterMethod(s); - } - - } - - static class keep_after_lastBI extends BuiltInForString { - class KeepAfterMethod implements TemplateMethodModelEx { - private String s; - - KeepAfterMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - String separatorString = getStringMethodArg(args, 0); - long flags = argCnt > 1 ? RegexpHelper.parseFlagString(getStringMethodArg(args, 1)) : 0; - - int startIndex; - if ((flags & RegexpHelper.RE_FLAG_REGEXP) == 0) { - RegexpHelper.checkOnlyHasNonRegexpFlags(key, flags, true); - if ((flags & RegexpHelper.RE_FLAG_CASE_INSENSITIVE) == 0) { - startIndex = s.lastIndexOf(separatorString); - } else { - startIndex = s.toLowerCase().lastIndexOf(separatorString.toLowerCase()); - } - if (startIndex >= 0) { - startIndex += separatorString.length(); - } - } else { - if (separatorString.length() == 0) { - startIndex = s.length(); - } else { - Pattern pattern = RegexpHelper.getPattern(separatorString, (int) flags); - final Matcher matcher = pattern.matcher(s); - if (matcher.find()) { - startIndex = matcher.end(); - while (matcher.find(matcher.start() + 1)) { - startIndex = matcher.end(); - } - } else { - startIndex = -1; - } - } - } - return startIndex == -1 ? TemplateScalarModel.EMPTY_STRING : new SimpleScalar(s.substring(startIndex)); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateModelException { - return new KeepAfterMethod(s); - } - - } - - static class keep_beforeBI extends BuiltInForString { - class KeepUntilMethod implements TemplateMethodModelEx { - private String s; - - KeepUntilMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - String separatorString = getStringMethodArg(args, 0); - long flags = argCnt > 1 ? RegexpHelper.parseFlagString(getStringMethodArg(args, 1)) : 0; - - int stopIndex; - if ((flags & RegexpHelper.RE_FLAG_REGEXP) == 0) { - RegexpHelper.checkOnlyHasNonRegexpFlags(key, flags, true); - if ((flags & RegexpHelper.RE_FLAG_CASE_INSENSITIVE) == 0) { - stopIndex = s.indexOf(separatorString); - } else { - stopIndex = s.toLowerCase().indexOf(separatorString.toLowerCase()); - } - } else { - Pattern pattern = RegexpHelper.getPattern(separatorString, (int) flags); - final Matcher matcher = pattern.matcher(s); - if (matcher.find()) { - stopIndex = matcher.start(); - } else { - stopIndex = -1; - } - } - return stopIndex == -1 ? new SimpleScalar(s) : new SimpleScalar(s.substring(0, stopIndex)); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateModelException { - return new KeepUntilMethod(s); - } - - } - - // TODO - static class keep_before_lastBI extends BuiltInForString { - class KeepUntilMethod implements TemplateMethodModelEx { - private String s; - - KeepUntilMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - String separatorString = getStringMethodArg(args, 0); - long flags = argCnt > 1 ? RegexpHelper.parseFlagString(getStringMethodArg(args, 1)) : 0; - - int stopIndex; - if ((flags & RegexpHelper.RE_FLAG_REGEXP) == 0) { - RegexpHelper.checkOnlyHasNonRegexpFlags(key, flags, true); - if ((flags & RegexpHelper.RE_FLAG_CASE_INSENSITIVE) == 0) { - stopIndex = s.lastIndexOf(separatorString); - } else { - stopIndex = s.toLowerCase().lastIndexOf(separatorString.toLowerCase()); - } - } else { - if (separatorString.length() == 0) { - stopIndex = s.length(); - } else { - Pattern pattern = RegexpHelper.getPattern(separatorString, (int) flags); - final Matcher matcher = pattern.matcher(s); - if (matcher.find()) { - stopIndex = matcher.start(); - while (matcher.find(stopIndex + 1)) { - stopIndex = matcher.start(); - } - } else { - stopIndex = -1; - } - } - } - return stopIndex == -1 ? new SimpleScalar(s) : new SimpleScalar(s.substring(0, stopIndex)); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateModelException { - return new KeepUntilMethod(s); - } - - } - - static class lengthBI extends BuiltInForString { - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new SimpleNumber(s.length()); - } - - } - - static class lower_caseBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(s.toLowerCase(env.getLocale())); - } - } - - static class padBI extends BuiltInForString { - - private class BIMethod implements TemplateMethodModelEx { - - private final String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - - int width = getNumberMethodArg(args, 0).intValue(); - - if (argCnt > 1) { - String filling = getStringMethodArg(args, 1); - try { - return new SimpleScalar( - leftPadder - ? _StringUtil.leftPad(s, width, filling) - : _StringUtil.rightPad(s, width, filling)); - } catch (IllegalArgumentException e) { - if (filling.length() == 0) { - throw new _TemplateModelException( - "?", key, "(...) argument #2 can't be a 0-length string."); - } else { - throw new _TemplateModelException(e, - "?", key, "(...) failed: ", e); - } - } - } else { - return new SimpleScalar(leftPadder ? _StringUtil.leftPad(s, width) : _StringUtil.rightPad(s, width)); - } - } - } - - private final boolean leftPadder; - - padBI(boolean leftPadder) { - this.leftPadder = leftPadder; - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new BIMethod(s); - } - } - - static class remove_beginningBI extends BuiltInForString { - - private class BIMethod implements TemplateMethodModelEx { - private String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1); - String prefix = getStringMethodArg(args, 0); - return new SimpleScalar(s.startsWith(prefix) ? s.substring(prefix.length()) : s); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new BIMethod(s); - } - } - - static class remove_endingBI extends BuiltInForString { - - private class BIMethod implements TemplateMethodModelEx { - private String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1); - String suffix = getStringMethodArg(args, 0); - return new SimpleScalar(s.endsWith(suffix) ? s.substring(0, s.length() - suffix.length()) : s); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new BIMethod(s); - } - } - - static class split_BI extends BuiltInForString { - class SplitMethod implements TemplateMethodModel { - private String s; - - SplitMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - int argCnt = args.size(); - checkMethodArgCount(argCnt, 1, 2); - String splitString = (String) args.get(0); - long flags = argCnt > 1 ? RegexpHelper.parseFlagString((String) args.get(1)) : 0; - String[] result = null; - if ((flags & RegexpHelper.RE_FLAG_REGEXP) == 0) { - RegexpHelper.checkNonRegexpFlags("split", flags); - result = _StringUtil.split(s, splitString, - (flags & RegexpHelper.RE_FLAG_CASE_INSENSITIVE) != 0); - } else { - Pattern pattern = RegexpHelper.getPattern(splitString, (int) flags); - result = pattern.split(s); - } - return _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER.wrap(result); - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateModelException { - return new SplitMethod(s); - } - - } - - static class starts_withBI extends BuiltInForString { - - private class BIMethod implements TemplateMethodModelEx { - private String s; - - private BIMethod(String s) { - this.s = s; - } - - @Override - public Object exec(List args) throws TemplateModelException { - checkMethodArgCount(args, 1); - return s.startsWith(getStringMethodArg(args, 0)) ? - TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } - } - - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - return new BIMethod(s); - } - } - - static class substringBI extends BuiltInForString { - - @Override - TemplateModel calculateResult(final String s, final Environment env) throws TemplateException { - return new TemplateMethodModelEx() { - - @Override - public Object exec(java.util.List args) throws TemplateModelException { - int argCount = args.size(); - checkMethodArgCount(argCount, 1, 2); - - int beginIdx = getNumberMethodArg(args, 0).intValue(); - - final int len = s.length(); - - if (beginIdx < 0) { - throw newIndexLessThan0Exception(0, beginIdx); - } else if (beginIdx > len) { - throw newIndexGreaterThanLengthException(0, beginIdx, len); - } - - if (argCount > 1) { - int endIdx = getNumberMethodArg(args, 1).intValue(); - if (endIdx < 0) { - throw newIndexLessThan0Exception(1, endIdx); - } else if (endIdx > len) { - throw newIndexGreaterThanLengthException(1, endIdx, len); - } - if (beginIdx > endIdx) { - throw MessageUtil.newMethodArgsInvalidValueException("?" + key, - "The begin index argument, ", Integer.valueOf(beginIdx), - ", shouldn't be greater than the end index argument, ", - Integer.valueOf(endIdx), "."); - } - return new SimpleScalar(s.substring(beginIdx, endIdx)); - } else { - return new SimpleScalar(s.substring(beginIdx)); - } - } - - private TemplateModelException newIndexGreaterThanLengthException( - int argIdx, int idx, final int len) throws TemplateModelException { - return MessageUtil.newMethodArgInvalidValueException( - "?" + key, argIdx, - "The index mustn't be greater than the length of the string, ", - Integer.valueOf(len), - ", but it was ", Integer.valueOf(idx), "."); - } - - private TemplateModelException newIndexLessThan0Exception( - int argIdx, int idx) throws TemplateModelException { - return MessageUtil.newMethodArgInvalidValueException( - "?" + key, argIdx, - "The index must be at least 0, but was ", Integer.valueOf(idx), "."); - } - - }; - } - } - - static class trimBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(s.trim()); - } - } - - static class uncap_firstBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - int i = 0; - int ln = s.length(); - while (i < ln && Character.isWhitespace(s.charAt(i))) { - i++; - } - if (i < ln) { - StringBuilder b = new StringBuilder(s); - b.setCharAt(i, Character.toLowerCase(s.charAt(i))); - s = b.toString(); - } - return new SimpleScalar(s); - } - } - - static class upper_caseBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(s.toUpperCase(env.getLocale())); - } - } - - static class word_listBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - SimpleSequence result = new SimpleSequence(); - StringTokenizer st = new StringTokenizer(s); - while (st.hasMoreTokens()) { - result.add(st.nextToken()); - } - return result; - } - } - - // Can't be instantiated - private BuiltInsForStringsBasic() { } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsEncoding.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsEncoding.java b/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsEncoding.java deleted file mode 100644 index d11739f..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsEncoding.java +++ /dev/null @@ -1,185 +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.UnsupportedEncodingException; -import java.util.List; - -import org.apache.freemarker.core.model.TemplateMethodModel; -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.impl.SimpleScalar; -import org.apache.freemarker.core.util._StringUtil; - -class BuiltInsForStringsEncoding { - - static class htmlBI extends BuiltInForLegacyEscaping { - - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.XHTMLEnc(s)); - } - - } - - static class j_stringBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.javaStringEnc(s)); - } - } - - static class js_stringBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.javaScriptStringEnc(s)); - } - } - - static class json_stringBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.jsonStringEnc(s)); - } - } - - static class rtfBI extends BuiltInForLegacyEscaping { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.RTFEnc(s)); - } - } - - static class urlBI extends BuiltInForString { - - static class UrlBIResult extends BuiltInsForStringsEncoding.AbstractUrlBIResult { - - protected UrlBIResult(BuiltIn parent, String target, Environment env) { - super(parent, target, env); - } - - @Override - protected String encodeWithCharset(String cs) throws UnsupportedEncodingException { - return _StringUtil.URLEnc(targetAsString, cs); - } - - } - - @Override - TemplateModel calculateResult(String s, Environment env) { - return new UrlBIResult(this, s, env); - } - - } - - static class urlPathBI extends BuiltInForString { - - static class UrlPathBIResult extends BuiltInsForStringsEncoding.AbstractUrlBIResult { - - protected UrlPathBIResult(BuiltIn parent, String target, Environment env) { - super(parent, target, env); - } - - @Override - protected String encodeWithCharset(String cs) throws UnsupportedEncodingException { - return _StringUtil.URLPathEnc(targetAsString, cs); - } - - } - - @Override - TemplateModel calculateResult(String s, Environment env) { - return new UrlPathBIResult(this, s, env); - } - - } - - static class xhtmlBI extends BuiltInForLegacyEscaping { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.XHTMLEnc(s)); - } - } - - static class xmlBI extends BuiltInForLegacyEscaping { - @Override - TemplateModel calculateResult(String s, Environment env) { - return new SimpleScalar(_StringUtil.XMLEnc(s)); - } - } - - // Can't be instantiated - private BuiltInsForStringsEncoding() { } - - static abstract class AbstractUrlBIResult implements - TemplateScalarModel, TemplateMethodModel { - - protected final BuiltIn parent; - protected final String targetAsString; - private final Environment env; - private String cachedResult; - - protected AbstractUrlBIResult(BuiltIn parent, String targetAsString, Environment env) { - this.parent = parent; - this.targetAsString = targetAsString; - this.env = env; - } - - protected abstract String encodeWithCharset(String cs) throws UnsupportedEncodingException; - - @Override - public Object exec(List args) throws TemplateModelException { - parent.checkMethodArgCount(args.size(), 1); - try { - return new SimpleScalar(encodeWithCharset((String) args.get(0))); - } catch (UnsupportedEncodingException e) { - throw new _TemplateModelException(e, "Failed to execute URL encoding."); - } - } - - @Override - public String getAsString() throws TemplateModelException { - if (cachedResult == null) { - String cs = env.getEffectiveURLEscapingCharset(); - if (cs == null) { - throw new _TemplateModelException( - "To do URL encoding, the framework that encloses " - + "FreeMarker must specify the output encoding " - + "or the URL encoding charset, so ask the " - + "programmers to fix it. Or, as a last chance, " - + "you can set the url_encoding_charset setting in " - + "the template, e.g. " - + "<#setting url_escaping_charset='ISO-8859-1'>, or " - + "give the charset explicitly to the buit-in, e.g. " - + "foo?url('ISO-8859-1')."); - } - try { - cachedResult = encodeWithCharset(cs); - } catch (UnsupportedEncodingException e) { - throw new _TemplateModelException(e, "Failed to execute URL encoding."); - } - } - return cachedResult; - } - - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d784b2b/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsMisc.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsMisc.java b/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsMisc.java deleted file mode 100644 index 729a1da..0000000 --- a/src/main/java/org/apache/freemarker/core/ast/BuiltInsForStringsMisc.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 java.io.StringReader; - -import org.apache.freemarker.core.Template; -import org.apache.freemarker.core.TemplateException; -import org.apache.freemarker.core.ast.FMParser; -import org.apache.freemarker.core.ast.FMParserConstants; -import org.apache.freemarker.core.ast.FMParserTokenManager; -import org.apache.freemarker.core.ast.SimpleCharStream; -import org.apache.freemarker.core.model.TemplateBooleanModel; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.impl.SimpleNumber; - -class BuiltInsForStringsMisc { - - static class booleanBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - final boolean b; - if (s.equals("true")) { - b = true; - } else if (s.equals("false")) { - b = false; - } else if (s.equals(env.getTrueStringValue())) { - b = true; - } else if (s.equals(env.getFalseStringValue())) { - b = false; - } else { - throw new _MiscTemplateException(this, env, - "Can't convert this string to boolean: ", new _DelayedJQuote(s)); - } - return b ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } - } - - static class evalBI extends OutputFormatBoundBuiltIn { - - @Override - protected TemplateModel calculateResult(Environment env) throws TemplateException { - return calculateResult(BuiltInForString.getTargetString(target, env), env); - } - - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - Template parentTemplate = getTemplate(); - - Expression exp = null; - try { - try { - ParserConfiguration pCfg = parentTemplate.getParserConfiguration(); - - SimpleCharStream simpleCharStream = new SimpleCharStream( - new StringReader("(" + s + ")"), - RUNTIME_EVAL_LINE_DISPLACEMENT, 1, - s.length() + 2); - simpleCharStream.setTabSize(pCfg.getTabSize()); - FMParserTokenManager tkMan = new FMParserTokenManager( - simpleCharStream); - tkMan.SwitchTo(FMParserConstants.FM_EXPRESSION); - - // pCfg.outputFormat is exceptional: it's inherited from the lexical context - if (pCfg.getOutputFormat() != outputFormat) { - pCfg = new _ParserConfigurationWithInheritedFormat( - pCfg, outputFormat, Integer.valueOf(autoEscapingPolicy)); - } - - FMParser parser = new FMParser( - parentTemplate, false, tkMan, pCfg, TemplateSpecifiedEncodingHandler.DEFAULT); - - exp = parser.Expression(); - } catch (TokenMgrError e) { - throw e.toParseException(parentTemplate); - } - } catch (ParseException e) { - throw new _MiscTemplateException(this, env, - "Failed to \"?", key, "\" string with this error:\n\n", - MessageUtil.EMBEDDED_MESSAGE_BEGIN, - new _DelayedGetMessage(e), - MessageUtil.EMBEDDED_MESSAGE_END, - "\n\nThe failing expression:"); - } - try { - return exp.eval(env); - } catch (TemplateException e) { - throw new _MiscTemplateException(this, env, - "Failed to \"?", key, "\" string with this error:\n\n", - MessageUtil.EMBEDDED_MESSAGE_BEGIN, - new _DelayedGetMessageWithoutStackTop(e), - MessageUtil.EMBEDDED_MESSAGE_END, - "\n\nThe failing expression:"); - } - } - - } - - static class numberBI extends BuiltInForString { - @Override - TemplateModel calculateResult(String s, Environment env) throws TemplateException { - try { - return new SimpleNumber(env.getArithmeticEngine().toNumber(s)); - } catch (NumberFormatException nfe) { - throw NonNumericalException.newMalformedNumberException(this, s, env); - } - } - } - - // Can't be instantiated - private BuiltInsForStringsMisc() { } - -}
