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