001    // Copyright 2006 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 org.apache.tapestry.IForm;
018    import org.apache.tapestry.IMarkupWriter;
019    import org.apache.tapestry.IRequestCycle;
020    
021    /**
022     * A {@link FormSupport} implementation that can work when a form is
023     * included multiple times in a given page ( due to it being in a loop
024     * or in a component that's included many times in the page).
025     * <p/>
026     * This is achieved by prefixing the ids of all form elements with the 
027     * form's id.
028     *
029     * @since 4.1.1
030     */
031    public class MultipleFormSupport extends FormSupportImpl
032    {   
033        /** 
034         * The prefix to use for the form elements. On render, this is the
035         * clientId of the form. On rewind, it's computed from the posted data.
036         */
037        private String _prefix;
038        
039        public MultipleFormSupport(IMarkupWriter writer, IRequestCycle cycle, IForm form)
040        {
041            super(writer, cycle, form);
042            _prefix = form.getClientId() + ":";
043        }
044        
045        /**
046         * Constructs a unique identifier (within the page). The identifier consists of the component's
047         * id, with an index number added to ensure uniqueness.
048         */
049    
050        public String getElementId(IFormComponent component, String baseId)
051        {
052            return super.getElementId(component, _prefix + baseId);
053        }
054        
055        public String peekClientId(IFormComponent comp)
056        {
057            String id = comp.getSpecifiedId();
058            if (id == null)
059                return null;
060            
061            return peekClientId(comp, id);
062        }    
063        
064        protected String peekClientId(IFormComponent comp, String baseId)
065        {        
066            return _elementIdAllocator.peekNextId(_prefix + baseId);
067        } 
068        
069        public String rewind()
070        {
071            findIdPrefix();
072            return super.rewind();
073        }
074        
075        private void findIdPrefix()
076        {
077            String allocatedFormIds = _cycle.getParameter(FORM_IDS);
078            if (allocatedFormIds==null)
079                return;
080            int pos = allocatedFormIds.indexOf(':');
081            if (pos>=0)
082                _prefix = allocatedFormIds.substring(0, pos + 1);
083        }    
084    }