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 }