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