/*
 * 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 freemarker.core;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import freemarker.template.SimpleSequence;
import freemarker.template.TemplateException;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateSequenceModel;

final class ListLiteral extends Expression {

    final ArrayList/*<Expression>*/ items;

    ListLiteral(ArrayList items) {
        this.items = items;
        items.trimToSize();
    }

    @Override
    TemplateModel _eval(Environment env) throws TemplateException {
        SimpleSequence list = new SimpleSequence(items.size());
        for (Iterator it = items.iterator(); it.hasNext(); ) {
            Expression exp = (Expression) it.next();
            TemplateModel tm = exp.eval(env);
            if (env == null || !env.isClassicCompatible()) {            
                exp.assertNonNull(tm, env);
            }
            list.add(tm);
        }
        return list;
    }

    
For TemplateMethodModel calls, but not for TemplateMethodModelEx-es, returns the list of arguments as String-s.
/** * For {@link TemplateMethodModel} calls, but not for {@link TemplateMethodModelEx}-es, returns the list of * arguments as {@link String}-s. */
List/*<String>*/ getValueList(Environment env) throws TemplateException { int size = items.size(); switch(size) { case 0: { return Collections.EMPTY_LIST; } case 1: { return Collections.singletonList(((Expression) items.get(0)).evalAndCoerceToPlainText(env)); } default: { List result = new ArrayList(items.size()); for (ListIterator iterator = items.listIterator(); iterator.hasNext(); ) { Expression exp = (Expression) iterator.next(); result.add(exp.evalAndCoerceToPlainText(env)); } return result; } } }
For TemplateMethodModelEx calls, returns the list of arguments as TemplateModel-s.
/** * For {@link TemplateMethodModelEx} calls, returns the list of arguments as {@link TemplateModel}-s. */
List/*<TemplateModel>*/ getModelList(Environment env) throws TemplateException { int size = items.size(); switch(size) { case 0: { return Collections.EMPTY_LIST; } case 1: { return Collections.singletonList(((Expression) items.get(0)).eval(env)); } default: { List result = new ArrayList(items.size()); for (ListIterator iterator = items.listIterator(); iterator.hasNext(); ) { Expression exp = (Expression) iterator.next(); result.add(exp.eval(env)); } return result; } } } @Override public String getCanonicalForm() { StringBuilder buf = new StringBuilder("["); int size = items.size(); for (int i = 0; i < size; i++) { Expression value = (Expression) items.get(i); buf.append(value.getCanonicalForm()); if (i != size - 1) { buf.append(", "); } } buf.append("]"); return buf.toString(); } @Override String getNodeTypeSymbol() { return "[...]"; } @Override boolean isLiteral() { if (constantValue != null) { return true; } for (int i = 0; i < items.size(); i++) { Expression exp = (Expression) items.get(i); if (!exp.isLiteral()) { return false; } } return true; } // A hacky routine used by VisitNode and RecurseNode TemplateSequenceModel evaluateStringsToNamespaces(Environment env) throws TemplateException { TemplateSequenceModel val = (TemplateSequenceModel) eval(env); SimpleSequence result = new SimpleSequence(val.size()); for (int i = 0; i < items.size(); i++) { Object itemExpr = items.get(i); if (itemExpr instanceof StringLiteral) { String s = ((StringLiteral) itemExpr).getAsString(); try { Environment.Namespace ns = env.importLib(s, null); result.add(ns); } catch (IOException ioe) { throw new _MiscTemplateException(((StringLiteral) itemExpr), "Couldn't import library ", new _DelayedJQuote(s), ": ", new _DelayedGetMessage(ioe)); } } else { result.add(val.get(i)); } } return result; } @Override protected Expression deepCloneWithIdentifierReplaced_inner( String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) { ArrayList clonedValues = (ArrayList) items.clone(); for (ListIterator iter = clonedValues.listIterator(); iter.hasNext(); ) { iter.set(((Expression) iter.next()).deepCloneWithIdentifierReplaced( replacedIdentifier, replacement, replacementState)); } return new ListLiteral(clonedValues); } @Override int getParameterCount() { return items != null ? items.size() : 0; } @Override Object getParameterValue(int idx) { checkIndex(idx); return items.get(idx); } @Override ParameterRole getParameterRole(int idx) { checkIndex(idx); return ParameterRole.ITEM_VALUE; } private void checkIndex(int idx) { if (items == null || idx >= items.size()) { throw new IndexOutOfBoundsException(); } } }