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 015package org.apache.tapestry.components; 016 017import java.util.Iterator; 018 019import org.apache.tapestry.AbstractComponent; 020import org.apache.tapestry.IBinding; 021import org.apache.tapestry.IMarkupWriter; 022import org.apache.tapestry.IRequestCycle; 023import org.apache.tapestry.Tapestry; 024import 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 039public 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}