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 }