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.Iterator; 018 019 import org.apache.hivemind.util.Defense; 020 import org.apache.tapestry.TapestryUtils; 021 import org.apache.tapestry.web.WebSession; 022 023 /** 024 * Utility methods to support implementations of 025 * {@link org.apache.tapestry.record.PropertyPersistenceStrategy}. This consists of code refactored 026 * out of {@link org.apache.tapestry.record.SessionPropertyPersistenceStrategy} to support other, 027 * similar, persistence types with different rules for how long values are stored in the session. 028 * 029 * @author Howard M. Lewis Ship 030 * @since 4.0 031 */ 032 public class RecordUtils 033 { 034 /** 035 * Builds a {@link PropertyChange} instance for the given key and value pulled from the 036 * {@link org.apache.tapestry.web.WebSession}. 037 * 038 * @param key 039 * a key, previously created by 040 * {@link #buildChangeKey(String, String, String, String, String)}, consisting of a 041 * strategy id, application id, page name, id path (optional), and a property name, 042 * all seperated by commas. 043 * @param value 044 * the value stored in the session with this key 045 * @return a {@link PropertyChange} storing the property name and id path (if any), and the 046 * value 047 */ 048 public static PropertyChange buildChange(String key, Object value) 049 { 050 String[] tokens = TapestryUtils.split(key); 051 052 // Either strategy-id, app-name,page-name,id-path,property 053 // or strategy-id,app-name,page-name,property 054 055 String idPath = (tokens.length == 5) ? tokens[3] : null; 056 String propertyName = tokens[tokens.length - 1]; 057 058 return new PropertyChangeImpl(idPath, propertyName, value); 059 } 060 061 /** 062 * Iterates over the attributes stored in the session, invoking a callback on each one that 063 * matches the given prefix, applicationid and page name. This is used to operate over all 064 * stored data for a particular combination of strategy, applicationId and page. 065 * 066 * @param strategyId 067 * a unique identifier for a particular implementation of 068 * {@link PropertyPersistenceStrategy} 069 * @param applicationId 070 * a unique id for the application 071 * @param pageName 072 * the name of the page 073 * @param session 074 * the session to search 075 * @param callback 076 * the callback to invoke on each matching attibute name 077 */ 078 public static void iterateOverMatchingAttributes(String strategyId, String applicationId, 079 String pageName, WebSession session, WebSessionAttributeCallback callback) 080 { 081 Defense.notNull(strategyId, "strategyId"); 082 Defense.notNull(applicationId, "applicationId"); 083 Defense.notNull(pageName, "pageName"); 084 Defense.notNull(session, "session"); 085 086 String prefix = strategyId + "," + applicationId + "," + pageName + ","; 087 088 Iterator i = session.getAttributeNames().iterator(); 089 while (i.hasNext()) 090 { 091 String name = (String) i.next(); 092 093 if (name.startsWith(prefix)) 094 callback.handleAttribute(session, name); 095 } 096 } 097 098 /** 099 * Builds a change key, used to identify the change within the {@link WebSession}. A change key 100 * can be used as a session attribute name, without reasonable fear of conflict. 101 * 102 * @param strategyId 103 * a unique identifier for a particular implementation of 104 * {@link PropertyPersistenceStrategy} 105 * @param applicationId 106 * a unique identifier for the application 107 * @param pageName 108 * the name of the page containing the change 109 * @param idPath 110 * the id path of the component within the page containing the page, possibly null 111 * @param propertyName 112 * the name of the property 113 * @return the above values, seperated by commas (well, no comma between the prefix and the 114 * application id) 115 */ 116 public static String buildChangeKey(String strategyId, String applicationId, String pageName, 117 String idPath, String propertyName) 118 { 119 Defense.notNull(strategyId, "strategyId"); 120 Defense.notNull(applicationId, "applicationId"); 121 Defense.notNull(pageName, "pageName"); 122 Defense.notNull(propertyName, "propertyName"); 123 124 StringBuffer buffer = new StringBuffer(strategyId); 125 126 buffer.append(","); 127 buffer.append(applicationId); 128 buffer.append(","); 129 buffer.append(pageName); 130 131 if (idPath != null) 132 { 133 buffer.append(","); 134 buffer.append(idPath); 135 } 136 137 buffer.append(","); 138 buffer.append(propertyName); 139 140 return buffer.toString(); 141 } 142 }