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.form; 016 017 import java.util.Iterator; 018 019 import org.apache.hivemind.ApplicationRuntimeException; 020 import org.apache.tapestry.IActionListener; 021 import org.apache.tapestry.IForm; 022 import org.apache.tapestry.IMarkupWriter; 023 import org.apache.tapestry.IRequestCycle; 024 import org.apache.tapestry.Tapestry; 025 import org.apache.tapestry.coerce.ValueConverter; 026 import org.apache.tapestry.listener.ListenerInvoker; 027 import org.apache.tapestry.services.DataSqueezer; 028 029 /** 030 * A specialized component used to edit a list of items within a form; it is similar to a 031 * {@link org.apache.tapestry.components.Foreach}but leverages hidden inputs within the 032 * <form> to store the items in the list. [ <a 033 * href="../../../../../ComponentReference/ListEdit.html">Component Reference </a>] 034 * 035 * @author Howard Lewis Ship 036 * @since 1.0.2 037 */ 038 039 public abstract class ListEdit extends AbstractFormComponent 040 { 041 /** 042 * @see org.apache.tapestry.form.AbstractFormComponent#renderFormComponent(org.apache.tapestry.IMarkupWriter, 043 * org.apache.tapestry.IRequestCycle) 044 */ 045 protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle) 046 { 047 this.render(writer, cycle, getSource()); 048 } 049 050 /** 051 * @see org.apache.tapestry.form.AbstractFormComponent#rewindFormComponent(org.apache.tapestry.IMarkupWriter, 052 * org.apache.tapestry.IRequestCycle) 053 */ 054 protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle) 055 { 056 String[] values = cycle.getParameters(getName()); 057 058 this.render(writer, cycle, (Iterator) getValueConverter().coerceValue( 059 values, 060 Iterator.class)); 061 } 062 063 protected void render(IMarkupWriter writer, IRequestCycle cycle, Iterator i) 064 { 065 // If the source (when rendering), or the submitted values (on submit) 066 // are null, then skip the remainder (nothing to update, nothing to 067 // render). 068 069 if (i == null) 070 return; 071 072 int index = 0; 073 074 String element = getElement(); 075 076 boolean indexBound = isParameterBound("index"); 077 078 while (i.hasNext()) 079 { 080 Object value = null; 081 082 if (indexBound) 083 setIndex(index++); 084 085 if (cycle.isRewinding()) 086 value = convertValue((String) i.next()); 087 else 088 { 089 value = i.next(); 090 writeValue(getForm(), getName(), value); 091 } 092 093 setValue(value); 094 095 getListenerInvoker().invokeListener(getListener(), this, cycle); 096 097 if (element != null) 098 { 099 writer.begin(element); 100 renderInformalParameters(writer, cycle); 101 } 102 103 renderBody(writer, cycle); 104 105 if (element != null) 106 writer.end(); 107 } 108 } 109 110 private void writeValue(IForm form, String name, Object value) 111 { 112 String externalValue; 113 114 try 115 { 116 externalValue = getDataSqueezer().squeeze(value); 117 } 118 catch (Exception ex) 119 { 120 throw new ApplicationRuntimeException(Tapestry.format( 121 "ListEdit.unable-to-convert-value", 122 value), this, null, ex); 123 } 124 125 form.addHiddenValue(name, externalValue); 126 } 127 128 private Object convertValue(String value) 129 { 130 try 131 { 132 return getDataSqueezer().unsqueeze(value); 133 } 134 catch (Exception ex) 135 { 136 throw new ApplicationRuntimeException(Tapestry.format( 137 "ListEdit.unable-to-convert-string", 138 value), this, null, ex); 139 } 140 } 141 142 public abstract String getElement(); 143 144 /** @since 2.2 * */ 145 146 public abstract IActionListener getListener(); 147 148 /** @since 3.0 * */ 149 150 public boolean isDisabled() 151 { 152 return false; 153 } 154 155 /** @since 4.0 */ 156 157 public abstract Iterator getSource(); 158 159 /** @since 4.0 */ 160 161 public abstract void setValue(Object value); 162 163 /** @since 4.0 */ 164 165 public abstract void setIndex(int index); 166 167 /** @since 4.0 */ 168 169 public abstract DataSqueezer getDataSqueezer(); 170 171 /** @since 4.0 */ 172 173 public abstract ValueConverter getValueConverter(); 174 175 /** 176 * Injected. 177 * 178 * @since 4.0 179 */ 180 181 public abstract ListenerInvoker getListenerInvoker(); 182 183 /** 184 * Returns false; ListEdit components can't take focus. 185 * 186 * @since 4.0 187 */ 188 protected boolean getCanTakeFocus() 189 { 190 return false; 191 } 192 193 public String getClientId() 194 { 195 // TODO Auto-generated method stub 196 return null; 197 } 198 199 public String getDisplayName() 200 { 201 // TODO Auto-generated method stub 202 return null; 203 } 204 205 }