001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.markup.html.list;
018
019import java.util.Iterator;
020
021import org.apache.wicket.Component;
022import org.apache.wicket.markup.repeater.AbstractRepeater;
023import org.apache.wicket.model.IModel;
024import org.apache.wicket.model.Model;
025import org.apache.wicket.util.collections.ReadOnlyIterator;
026
027/**
028 * A very simple loop component whose model is an Integer defining the number of iterations the loop
029 * should render. During rendering, Loop iterates from 0 to getIterations() - 1, creating a new
030 * MarkupContainer for each iteration. The MarkupContainer is populated by the Loop subclass by
031 * implementing the abstract method populate(LoopItem). The populate() method is called just before
032 * the LoopItem container is rendered.
033 * 
034 * @author Juergen Donnerstag
035 * @author Eelco Hillenius
036 * @author Jonathan Locke
037 */
038public abstract class Loop extends AbstractRepeater
039{
040        private static final long serialVersionUID = 1L;
041
042        /**
043         * Construct.
044         * 
045         * @param id
046         *            See Component
047         * @param iterations
048         *            max index of the loop
049         * @see org.apache.wicket.Component#Component(String, IModel)
050         */
051        public Loop(final String id, final int iterations)
052        {
053                super(id, new Model<Integer>(iterations));
054        }
055
056        /**
057         * Construct.
058         * 
059         * @param id
060         *            See Component
061         * @param model
062         *            Must contain a Integer model object
063         * @see org.apache.wicket.Component#Component(String, IModel)
064         */
065        public Loop(final String id, final IModel<Integer> model)
066        {
067                super(id, model);
068        }
069
070        /**
071         * @return The number of loop iterations
072         */
073        public final int getIterations()
074        {
075                return (Integer)getDefaultModelObject();
076        }
077
078        /**
079         * @see org.apache.wicket.Component#onBeforeRender()
080         */
081        @Override
082        protected final void onPopulate()
083        {
084                // Remove any previous loop contents
085                removeAll();
086
087                // Get number of iterations
088                final int iterations = getIterations();
089                if (iterations > 0)
090                {
091                        // Create LoopItems for each iteration
092                        for (int iteration = 0; iteration < iterations; iteration++)
093                        {
094                                // Create item for loop iteration
095                                LoopItem item = newItem(iteration);
096
097                                // Add and populate item
098                                add(item);
099                                populateItem(item);
100                        }
101                }
102        }
103
104        /**
105         * Create a new LoopItem for loop at iteration.
106         * 
107         * @param iteration
108         *            iteration in the loop
109         * @return LoopItem
110         */
111        protected LoopItem newItem(int iteration)
112        {
113                return new LoopItem(iteration);
114        }
115
116        /**
117         * @see org.apache.wicket.markup.repeater.AbstractRepeater#renderIterator()
118         */
119        @Override
120        protected Iterator<Component> renderIterator()
121        {
122                final int iterations = size();
123
124                return new ReadOnlyIterator<Component>()
125                {
126                        private int index = 0;
127
128                        @Override
129                        public boolean hasNext()
130                        {
131                                return index < iterations;
132                        }
133
134                        @Override
135                        public Component next()
136                        {
137                                return get(Integer.toString(index++));
138                        }
139                };
140        }
141
142        /**
143         * Populates this loop item.
144         * 
145         * @param item
146         *            The iteration of the loop
147         */
148        protected abstract void populateItem(LoopItem item);
149
150        /**
151         * @param child
152         */
153        @Override
154        protected final void renderChild(Component child)
155        {
156                renderItem((LoopItem)child);
157        }
158
159        /**
160         * Renders this loop iteration.
161         * 
162         * @param item
163         *            The loop iteration
164         */
165        protected void renderItem(final LoopItem item)
166        {
167                item.render();
168        }
169}