/*
 * 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.ext.beans;

import java.util.Collection;
import java.util.List;

import freemarker.ext.util.ModelFactory;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelIterator;
import freemarker.template.TemplateSequenceModel;

A special case of BeanModel that can wrap Java collections and that implements the TemplateCollectionModel in order to be usable in a <#list> block.

/** * <p>A special case of {@link BeanModel} that can wrap Java collections * and that implements the {@link TemplateCollectionModel} in order to be usable * in a <tt>&lt;#list&gt;</tt> block.</p> */
public class CollectionModel extends StringModel implements TemplateCollectionModel, TemplateSequenceModel { static final ModelFactory FACTORY = new ModelFactory() { public TemplateModel create(Object object, ObjectWrapper wrapper) { return new CollectionModel((Collection) object, (BeansWrapper) wrapper); } };
Creates a new model that wraps the specified collection object.
Params:
  • collection – the collection object to wrap into a model.
  • wrapper – the BeansWrapper associated with this model. Every model has to have an associated BeansWrapper instance. The model gains many attributes from its wrapper, including the caching behavior, method exposure level, method-over-item shadowing policy etc.
/** * Creates a new model that wraps the specified collection object. * @param collection the collection object to wrap into a model. * @param wrapper the {@link BeansWrapper} associated with this model. * Every model has to have an associated {@link BeansWrapper} instance. The * model gains many attributes from its wrapper, including the caching * behavior, method exposure level, method-over-item shadowing policy etc. */
public CollectionModel(Collection collection, BeansWrapper wrapper) { super(collection, wrapper); }
Retrieves the i-th object from the collection, wrapped as a TemplateModel.
Throws:
  • TemplateModelException – if the index is out of bounds, or the underlying collection is not a List.
/** * Retrieves the i-th object from the collection, wrapped as a TemplateModel. * @throws TemplateModelException if the index is out of bounds, or the * underlying collection is not a List. */
public TemplateModel get(int index) throws TemplateModelException { // Don't forget to keep getSupportsIndexedAccess in sync with this! if (object instanceof List) { try { return wrap(((List) object).get(index)); } catch (IndexOutOfBoundsException e) { return null; // throw new TemplateModelException("Index out of bounds: " + index); } } else { throw new TemplateModelException("Underlying collection is not a list, it's " + object.getClass().getName()); } }
Tells if get(int) will always fail for this object. As this object implements TemplateSequenceModel, get(int) should always work, but due to a design flaw, for non-List wrapped objects get(int) will always fail. This method exists to ease working this problem around.
Since:2.3.17
/** * Tells if {@link #get(int)} will always fail for this object. * As this object implements {@link TemplateSequenceModel}, * {@link #get(int)} should always work, but due to a design flaw, for * non-{@link List} wrapped objects {@link #get(int)} will always fail. * This method exists to ease working this problem around. * * @since 2.3.17 */
public boolean getSupportsIndexedAccess() { return object instanceof List; } public TemplateModelIterator iterator() { return new IteratorModel(((Collection) object).iterator(), wrapper); } @Override public int size() { return ((Collection) object).size(); } }