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 }