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
028 * values. [ <a href="../../../../../ComponentReference/Foreach.html">Component
029 * Reference </a>]
030 * <p>
031 * While the component is rendering, the property {@link #getValue() value}(accessed
032 * as <code>components.<i>foreach</i>.value</code> is set to each successive
033 * value from the source, and the property {@link #getIndex() index}is set to
034 * each successive index into the source (starting with zero).
035 *
036 * @author Howard Lewis Ship
037 * @deprecated As of release 4.0, replaced by {@link ForBean}
038 */
039
040 public abstract class Foreach extends AbstractComponent
041 {
042
043 private Object _value;
044
045 private int _index;
046
047 /**
048 * Gets the source binding and returns an {@link Iterator}representing the
049 * values identified by the source. Returns an empty {@link Iterator}if the
050 * binding, or the binding value, is null.
051 * <p>
052 * Invokes {@link Tapestry#coerceToIterator(Object)}to perform the actual
053 * conversion.
054 */
055
056 protected Iterator getSourceData()
057 {
058 Object source = null;
059
060 IBinding sourceBinding = getBinding("source");
061 if (sourceBinding != null) source = sourceBinding.getObject();
062
063 if (source == null) return null;
064
065 return (Iterator) getValueConverter().coerceValue(source,
066 Iterator.class);
067 }
068
069 protected void prepareForRender(IRequestCycle cycle)
070 {
071 _value = null;
072 _index = 0;
073 }
074
075 protected void cleanupAfterRender(IRequestCycle cycle)
076 {
077 _value = null;
078 }
079
080 /**
081 * Gets the source binding and iterates through its values. For each, it
082 * updates the value binding and render's its wrapped elements.
083 */
084
085 protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
086 {
087 Iterator dataSource = getSourceData();
088
089 // The dataSource was either not convertable, or was empty.
090
091 if (dataSource == null) return;
092
093 boolean indexBound = isParameterBound("index");
094 boolean valueBound = isParameterBound("value");
095
096 String element = getElement();
097
098 boolean hasNext = dataSource.hasNext();
099
100 while(hasNext)
101 {
102 _value = dataSource.next();
103 hasNext = dataSource.hasNext();
104
105 if (indexBound) setIndexParameter(_index);
106
107 if (valueBound) 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) writer.end();
118
119 _index++;
120 }
121
122 }
123
124 /**
125 * Returns the most recent value extracted from the source parameter.
126 *
127 * @throws org.apache.tapestry.ApplicationRuntimeException
128 * if the Foreach is not currently rendering.
129 */
130
131 public Object getValue()
132 {
133 if (!isRendering())
134 throw Tapestry.createRenderOnlyPropertyException(this, "value");
135
136 return _value;
137 }
138
139 /**
140 * The index number, within the {@link #getSource() source}, of the the
141 * 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 }