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 }