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.ArrayList; 018 import java.util.HashMap; 019 import java.util.Iterator; 020 import java.util.List; 021 import java.util.Map; 022 023 import org.apache.hivemind.util.Defense; 024 025 /** 026 * Stores persistent property changes concerning a single page. The data may be 027 * stored as an encoded string and the PPD can turn between encoded and object 028 * form. 029 * 030 * @author Howard M. Lewis Ship 031 * @since 4.0 032 */ 033 public class PersistentPropertyData 034 { 035 036 /** 037 * Keyed on {@link org.apache.tapestry.record.ChangeKey}, values are new 038 * objects. 039 */ 040 041 private Map _changes; 042 043 private String _encoded; 044 045 private final PersistentPropertyDataEncoder _encoder; 046 047 /** 048 * Creates a new data using the specified encoder. The set of page changes 049 * is initially empty. 050 */ 051 052 public PersistentPropertyData(PersistentPropertyDataEncoder encoder) 053 { 054 Defense.notNull(encoder, "encoder"); 055 056 _encoder = encoder; 057 _changes = new HashMap(); 058 } 059 060 public String getEncoded() 061 { 062 if (_encoded == null) _encoded = encode(); 063 064 return _encoded; 065 } 066 067 public List getPageChanges() 068 { 069 if (_changes == null) 070 { 071 List pageChanges = _encoder.decodePageChanges(_encoded); 072 073 _changes = decode(pageChanges); 074 075 return pageChanges; 076 } 077 078 return createPageChangeList(); 079 } 080 081 public void store(String componentPath, String propertyName, Object newValue) 082 { 083 Defense.notNull(propertyName, "propertyName"); 084 085 if (_changes == null) 086 _changes = decode(_encoder.decodePageChanges(_encoded)); 087 088 ChangeKey key = new ChangeKey(componentPath, propertyName); 089 090 _changes.put(key, newValue); 091 092 // With the new (or changed) value, the encoded string is no 093 // longer valid. 094 095 _encoded = null; 096 } 097 098 public void storeEncoded(String encoded) 099 { 100 Defense.notNull(encoded, "encoded"); 101 102 _encoded = encoded; 103 104 // The decoded data is no longer valid now. 105 106 _changes = null; 107 } 108 109 private List createPageChangeList() 110 { 111 List result = new ArrayList(); 112 113 Iterator i = _changes.entrySet().iterator(); 114 115 while(i.hasNext()) 116 { 117 Map.Entry me = (Map.Entry) i.next(); 118 119 ChangeKey changeKey = (ChangeKey) me.getKey(); 120 Object value = me.getValue(); 121 122 PropertyChange change = new PropertyChangeImpl(changeKey.getComponentPath(), changeKey.getPropertyName(), value); 123 124 result.add(change); 125 } 126 127 return result; 128 } 129 130 private String encode() 131 { 132 List changes = createPageChangeList(); 133 134 return _encoder.encodePageChanges(changes); 135 } 136 137 private Map decode(List pageChanges) 138 { 139 Map result = new HashMap(); 140 141 Iterator i = pageChanges.iterator(); 142 while(i.hasNext()) 143 { 144 PropertyChange pc = (PropertyChange) i.next(); 145 146 String propertyName = pc.getPropertyName(); 147 String componentPath = pc.getComponentPath(); 148 149 ChangeKey key = new ChangeKey(componentPath, propertyName); 150 151 result.put(key, pc.getNewValue()); 152 } 153 154 return result; 155 } 156 }