001    // Copyright 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.record;
016    
017    import java.util.Collection;
018    import java.util.Collections;
019    import java.util.HashMap;
020    import java.util.Iterator;
021    import java.util.List;
022    import java.util.Map;
023    
024    import org.apache.hivemind.util.Defense;
025    import org.apache.tapestry.engine.ServiceEncoding;
026    import org.apache.tapestry.web.WebRequest;
027    
028    /**
029     * Service tapestry.persist.ClientPropertyPersistenceStrategy. Encodes persistent page properties on
030     * the client as query parameters.
031     * <p>
032     * Uses the threaded model.
033     * 
034     * @author Howard M. Lewis Ship
035     * @since 4.0
036     * @see org.apache.tapestry.engine.ILink
037     */
038    public class ClientPropertyPersistenceStrategy implements PropertyPersistenceStrategy
039    {
040        /**
041         * Keyed on page name (String), values are
042         * {@link org.apache.tapestry.record.PersistentPropertyData}.
043         */
044        private final Map _data = new HashMap();
045    
046        private PersistentPropertyDataEncoder _encoder;
047    
048        private WebRequest _request;
049    
050        private ClientPropertyPersistenceScope _scope;
051    
052        /**
053         * Initializer for this service, invoked every time a service instance is created. This
054         * initializer pulls out of the request and query parameters whose prefix is "client:" and
055         * expects them to be encoded {@link PersistentPropertyData}, which are stored internally.
056         * Because the service model is threaded, this information is specific to a single request, and
057         * will be discarded at the end of the request.
058         */
059    
060        public void initializeService()
061        {
062            List names = _request.getParameterNames();
063            Iterator i = names.iterator();
064            while (i.hasNext())
065            {
066                String name = (String) i.next();
067    
068                if (!_scope.isParameterForScope(name))
069                    continue;
070    
071                String pageName = _scope.extractPageName(name);
072    
073                String encoded = _request.getParameterValue(name);
074    
075                PersistentPropertyData data = new PersistentPropertyData(_encoder);
076                data.storeEncoded(encoded);
077    
078                _data.put(pageName, data);
079            }
080        }
081    
082        public void store(String pageName, String idPath, String propertyName, Object newValue)
083        {
084            PersistentPropertyData data = (PersistentPropertyData) _data.get(pageName);
085            if (data == null)
086            {
087                data = new PersistentPropertyData(_encoder);
088                _data.put(pageName, data);
089            }
090    
091            data.store(idPath, propertyName, newValue);
092        }
093    
094        public Collection getStoredChanges(String pageName)
095        {
096            PersistentPropertyData data = (PersistentPropertyData) _data.get(pageName);
097    
098            if (data == null)
099                return Collections.EMPTY_LIST;
100    
101            return data.getPageChanges();
102        }
103    
104        public void discardStoredChanges(String pageName)
105        {
106            _data.remove(pageName);
107        }
108    
109        public void addParametersForPersistentProperties(ServiceEncoding encoding, boolean post)
110        {
111            Defense.notNull(encoding, "encoding");
112     
113            Iterator i = _data.entrySet().iterator();
114            while (i.hasNext())
115            {
116                Map.Entry e = (Map.Entry) i.next();
117    
118                String pageName = (String) e.getKey();
119                PersistentPropertyData data = (PersistentPropertyData) e.getValue();
120    
121                ClientPropertyPersistenceScope scope = getScope();
122    
123                if (scope.shouldEncodeState(encoding, pageName, data))
124                {
125                    String parameterName = _scope.constructParameterName(pageName);
126                    encoding.setParameterValue(parameterName, data.getEncoded());
127                }
128            }
129        }
130    
131        public void setRequest(WebRequest request)
132        {
133            _request = request;
134        }
135    
136        public ClientPropertyPersistenceScope getScope()
137        {
138            return _scope;
139        }
140    
141        public void setScope(ClientPropertyPersistenceScope scope)
142        {
143            _scope = scope;
144        }
145    
146        public void setEncoder(PersistentPropertyDataEncoder encoder)
147        {
148            _encoder = encoder;
149        }
150    }