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