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

import java.io.Serializable;
import java.util.AbstractSequentialList;
import java.util.List;

import freemarker.ext.util.WrapperTemplateModel;
import freemarker.template.utility.ObjectWrapperWithAPISupport;
import freemarker.template.utility.RichObjectWrapper;

Adapts a List to the corresponding TemplateModel interface(s), most importantly to TemplateSequenceModel. If you aren't wrapping an already existing List, but build a sequence specifically to be used from a template, also consider using SimpleSequence (see comparison there).

Thread safety: A DefaultListAdapter is as thread-safe as the List that it wraps is. Normally you only have to consider read-only access, as the FreeMarker template language doesn't allow writing these sequences (though of course, Java methods called from the template can violate this rule).

This adapter is used by DefaultObjectWrapper if its useAdaptersForCollections property is true, which is the default when its incompatibleImprovements property is 2.3.22 or higher.

See Also:
Since:2.3.22
/** * Adapts a {@link List} to the corresponding {@link TemplateModel} interface(s), most importantly to * {@link TemplateSequenceModel}. If you aren't wrapping an already existing {@link List}, but build a sequence * specifically to be used from a template, also consider using {@link SimpleSequence} (see comparison there). * * <p> * Thread safety: A {@link DefaultListAdapter} is as thread-safe as the {@link List} that it wraps is. Normally you only * have to consider read-only access, as the FreeMarker template language doesn't allow writing these sequences (though * of course, Java methods called from the template can violate this rule). * * <p> * This adapter is used by {@link DefaultObjectWrapper} if its {@code useAdaptersForCollections} property is * {@code true}, which is the default when its {@code incompatibleImprovements} property is 2.3.22 or higher. * * @see SimpleSequence * @see DefaultArrayAdapter * @see TemplateSequenceModel * * @since 2.3.22 */
public class DefaultListAdapter extends WrappingTemplateModel implements TemplateSequenceModel, AdapterTemplateModel, WrapperTemplateModel, TemplateModelWithAPISupport, Serializable { protected final List list;
Factory method for creating new adapter instances.
Params:
  • list – The list to adapt; can't be null.
  • wrapper – The ObjectWrapper used to wrap the items in the array.
/** * Factory method for creating new adapter instances. * * @param list * The list to adapt; can't be {@code null}. * @param wrapper * The {@link ObjectWrapper} used to wrap the items in the array. */
public static DefaultListAdapter adapt(List list, RichObjectWrapper wrapper) { // [2.4] DefaultListAdapter should implement TemplateCollectionModelEx, so this choice becomes unnecessary return list instanceof AbstractSequentialList ? new DefaultListAdapterWithCollectionSupport(list, wrapper) : new DefaultListAdapter(list, wrapper); } private DefaultListAdapter(List list, RichObjectWrapper wrapper) { super(wrapper); this.list = list; } public TemplateModel get(int index) throws TemplateModelException { return index >= 0 && index < list.size() ? wrap(list.get(index)) : null; } public int size() throws TemplateModelException { return list.size(); } public Object getAdaptedObject(Class hint) { return getWrappedObject(); } public Object getWrappedObject() { return list; } private static class DefaultListAdapterWithCollectionSupport extends DefaultListAdapter implements TemplateCollectionModel { private DefaultListAdapterWithCollectionSupport(List list, RichObjectWrapper wrapper) { super(list, wrapper); } public TemplateModelIterator iterator() throws TemplateModelException { return new IteratorToTemplateModelIteratorAdapter(list.iterator(), getObjectWrapper()); } } public TemplateModel getAPI() throws TemplateModelException { return ((ObjectWrapperWithAPISupport) getObjectWrapper()).wrapAsAPI(list); } }