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