All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.trinidad.util.ListFromCollection Maven / Gradle / Ivy

/*
 * 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.myfaces.trinidad.util;

import java.util.AbstractMap;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;
import java.util.Set;

/**
 * 

* Bean that can dynamically produce Lists from Collections. * The Collections must implement size(). Create an instance * of this bean as a managed bean: *

*

Example:

*
 *  <managed-bean>
 *    <managed-bean-name>makeList</managed-bean-name>
 *    <managed-bean-class>
 *       org.apache.myfaces.trinidad.util.ListFromCollection
 *    </managed-bean-class>
 *    <managed-bean-scope>
 *       request
 *    </managed-bean-scope>
 *    <!-- Let's buffer 25 rows at a time (the default is 50) -->
 *    <managed-property>
 *      <property-name>size</property-name>
 *      <value>25</value>
 *    <managed-property>
 *  </managed-bean>
 * 
*
 *   <h:dataTable value="#{makeList.list[someSet]}>
 *   </h:dataTable>
 * 
*

* Note, though, that it is extremely expensive to use this bean for * the items of an tr:forEach (or c:forEach in JSF 1.2 or Facelets). *

*/ public class ListFromCollection { public ListFromCollection() { _map = new MakeList(); _size = _DEFAULT_SIZE; } public Map, List> getList() { return _map; } public int getSize() { return _size; } public void setSize(int size) { _size = size; } private class MakeList extends AbstractMap, List> { @Override public List get(Object o) { if (!(o instanceof Collection)) return null; // Just send RandomAccess lists out; wrap any other Collection // into a List if ((o instanceof List) && (o instanceof RandomAccess)) return (List) o; Collection c = (Collection) o; if (c.isEmpty()) return Collections.emptyList(); return new ListImpl(c, getSize()); } @Override public Set, List>> entrySet() { // Not worth implementing at the moment; this Map is only // accessed from return Collections.emptySet(); } } private static class ListImpl extends AbstractList { public ListImpl(Collection c, int size) { _c = c; _cSize = c.size(); if (size == 0) _bufferSize = _cSize; else _bufferSize = Math.min(size, _cSize); _buffer = new ArrayList(_bufferSize); _offset = -1; } @Override public int size() { return _cSize; } @Override public Object get(int index) { if ((index < 0) || (index >= _cSize)) throw new IndexOutOfBoundsException(); int offset = (index / _bufferSize) * _bufferSize; if (offset != _offset) { _loadBuffer(offset); _offset = offset; } return _buffer.get(index - _offset); } private void _loadBuffer(int offset) { Iterator iter = _c.iterator(); int i = 0; while (i < offset) { assert iter.hasNext(); iter.next(); i++; } _buffer.clear(); int count = 0; while ((count < _bufferSize) && (i < _cSize)) { assert iter.hasNext(); _buffer.add(iter.next()); i++; count++; } } private final Collection _c; private final int _bufferSize; private final int _cSize; private int _offset; private ArrayList _buffer; } private Map, List> _map; private int _size; static private int _DEFAULT_SIZE = 50; }