001 // Copyright 2004, 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry.components;
016
017 import java.util.Iterator;
018
019 import org.apache.tapestry.AbstractComponent;
020 import org.apache.tapestry.IBinding;
021 import org.apache.tapestry.IMarkupWriter;
022 import org.apache.tapestry.IRequestCycle;
023 import org.apache.tapestry.Tapestry;
024 import org.apache.tapestry.coerce.ValueConverter;
025
026 /**
027 * Repeatedly renders its wrapped contents while iterating through a list of values. [ <a
028 * href="../../../../../ComponentReference/Foreach.html">Component Reference </a>]
029 * <p>
030 * While the component is rendering, the property {@link #getValue() value}(accessed as
031 * <code>components.<i>foreach</i>.value</code> is set to each successive value from the source,
032 * and the property {@link #getIndex() index}is set to each successive index into the source
033 * (starting with zero).
034 *
035 * @author Howard Lewis Ship
036 * @deprecated As of release 4.0, replaced by {@link ForBean}
037 */
038
039 public abstract class Foreach extends AbstractComponent
040 {
041 private Object _value;
042
043 private int _index;
044
045 /**
046 * Gets the source binding and returns an {@link Iterator}representing the values identified by
047 * the source. Returns an empty {@link Iterator}if the binding, or the binding value, is null.
048 * <p>
049 * Invokes {@link Tapestry#coerceToIterator(Object)}to perform the actual conversion.
050 */
051
052 protected Iterator getSourceData()
053 {
054 Object source = null;
055
056 IBinding sourceBinding = getBinding("source");
057 if (sourceBinding != null)
058 source = sourceBinding.getObject();
059
060 if (source == null)
061 return null;
062
063 return (Iterator) getValueConverter().coerceValue(source, Iterator.class);
064 }
065
066 protected void prepareForRender(IRequestCycle cycle)
067 {
068 _value = null;
069 _index = 0;
070 }
071
072 protected void cleanupAfterRender(IRequestCycle cycle)
073 {
074 _value = null;
075 }
076
077 /**
078 * Gets the source binding and iterates through its values. For each, it updates the value
079 * binding and render's its wrapped elements.
080 */
081
082 protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
083 {
084 Iterator dataSource = getSourceData();
085
086 // The dataSource was either not convertable, or was empty.
087
088 if (dataSource == null)
089 return;
090
091 boolean indexBound = isParameterBound("index");
092 boolean valueBound = isParameterBound("value");
093
094 String element = getElement();
095
096 boolean hasNext = dataSource.hasNext();
097
098 while (hasNext)
099 {
100 _value = dataSource.next();
101 hasNext = dataSource.hasNext();
102
103 if (indexBound)
104 setIndexParameter(_index);
105
106 if (valueBound)
107 setValueParameter(_value);
108
109 if (element != null)
110 {
111 writer.begin(element);
112 renderInformalParameters(writer, cycle);
113 }
114
115 renderBody(writer, cycle);
116
117 if (element != null)
118 writer.end();
119
120 _index++;
121 }
122
123 }
124
125 /**
126 * Returns the most recent value extracted from the source parameter.
127 *
128 * @throws org.apache.tapestry.ApplicationRuntimeException
129 * if the Foreach is not currently rendering.
130 */
131
132 public Object getValue()
133 {
134 if (!isRendering())
135 throw Tapestry.createRenderOnlyPropertyException(this, "value");
136
137 return _value;
138 }
139
140 /**
141 * The index number, within the {@link #getSource() source}, of the the current value.
142 *
143 * @throws org.apache.tapestry.ApplicationRuntimeException
144 * if the Foreach is not currently rendering.
145 * @since 2.2
146 */
147
148 public int getIndex()
149 {
150 if (!isRendering())
151 throw Tapestry.createRenderOnlyPropertyException(this, "index");
152
153 return _index;
154 }
155
156 public abstract String getElement();
157
158 /** @since 4.0 */
159 public abstract void setIndexParameter(int value);
160
161 /** @since 4.0 */
162 public abstract void setValueParameter(Object value);
163
164 /** @since 4.0 */
165 public abstract ValueConverter getValueConverter();
166 }