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 }