001 /*
002 * The MIT License
003 * Copyright (c) 2012 Microsoft Corporation
004 *
005 * Permission is hereby granted, free of charge, to any person obtaining a copy
006 * of this software and associated documentation files (the "Software"), to deal
007 * in the Software without restriction, including without limitation the rights
008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
009 * copies of the Software, and to permit persons to whom the Software is
010 * furnished to do so, subject to the following conditions:
011 *
012 * The above copyright notice and this permission notice shall be included in
013 * all copies or substantial portions of the Software.
014 *
015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
021 * THE SOFTWARE.
022 */
023
024 package microsoft.exchange.webservices.data.core;
025
026 import microsoft.exchange.webservices.data.misc.OutParam;
027 import microsoft.exchange.webservices.data.property.complex.IPropertyBagChangedDelegate;
028
029 import java.util.ArrayList;
030 import java.util.HashMap;
031 import java.util.Iterator;
032 import java.util.List;
033 import java.util.Map;
034
035 /**
036 * Represents a simple property bag.
037 *
038 * @param <TKey> The type of key
039 */
040 public class SimplePropertyBag<TKey> implements Iterable<HashMap<TKey, Object>> {
041
042 /**
043 * The item.
044 */
045 private Map<TKey, Object> items = new HashMap<TKey, Object>();
046
047 /**
048 * The removed item.
049 */
050 private List<TKey> removedItems = new ArrayList<TKey>();
051
052 /**
053 * The added item.
054 */
055 private List<TKey> addedItems = new ArrayList<TKey>();
056
057 /**
058 * The modified item.
059 */
060 private List<TKey> modifiedItems = new ArrayList<TKey>();
061
062 /**
063 * Add item to change list.
064 *
065 * @param key the key
066 * @param changeList the change list
067 */
068 private void internalAddItemToChangeList(TKey key, List<TKey> changeList) {
069 if (!changeList.contains(key)) {
070 changeList.add(key);
071 }
072 }
073
074 /**
075 * Triggers dispatch of the change event.
076 */
077 private void changed() {
078 if (!onChange.isEmpty()) {
079 for (IPropertyBagChangedDelegate<TKey> change : onChange) {
080 change.propertyBagChanged(this);
081 }
082 }
083 }
084
085 /**
086 * Remove item.
087 *
088 * @param key the key
089 */
090 private void internalRemoveItem(TKey key) {
091 OutParam<Object> value = new OutParam<Object>();
092 if (this.tryGetValue(key, value)) {
093 this.items.remove(key);
094 this.removedItems.add(key);
095 this.changed();
096 }
097 }
098
099
100 /**
101 * Gets the added item. <value>The added item.</value>
102 *
103 * @return the added item
104 */
105 public Iterable<TKey> getAddedItems() {
106 return this.addedItems;
107 }
108
109 /**
110 * Gets the removed item. <value>The removed item.</value>
111 *
112 * @return the removed item
113 */
114 public Iterable<TKey> getRemovedItems() {
115 return this.removedItems;
116 }
117
118 /**
119 * Gets the modified item. <value>The modified item.</value>
120 *
121 * @return the modified item
122 */
123 public Iterable<TKey> getModifiedItems() {
124 return this.modifiedItems;
125 }
126
127 /**
128 * Initializes a new instance of the class.
129 */
130 public SimplePropertyBag() {
131 }
132
133 /**
134 * Clears the change log.
135 */
136 public void clearChangeLog() {
137 this.removedItems.clear();
138 this.addedItems.clear();
139 this.modifiedItems.clear();
140 }
141
142 /**
143 * Determines whether the specified key is in the property bag.
144 *
145 * @param key the key
146 * @return true, if successful if the specified key exists; otherwise, .
147 */
148 public boolean containsKey(TKey key) {
149 return this.items.containsKey(key);
150 }
151
152 /**
153 * Tries to get value.
154 *
155 * @param key the key
156 * @param value the value
157 * @return True if value exists in property bag.
158 */
159 public boolean tryGetValue(TKey key, OutParam<Object> value) {
160 if (this.items.containsKey(key)) {
161 value.setParam(this.items.get(key));
162 return true;
163 } else {
164 value.setParam(null);
165 return false;
166 }
167 }
168
169 /**
170 * Gets the simple property bag.
171 *
172 * @param key the key
173 * @return the simple property bag
174 */
175 public Object getSimplePropertyBag(TKey key) {
176 OutParam<Object> value = new OutParam<Object>();
177 if (this.tryGetValue(key, value)) {
178 return value.getParam();
179 } else {
180 return null;
181 }
182 }
183
184 /**
185 * Sets the simple property bag.
186 *
187 * @param key the key
188 * @param value the value
189 */
190 public void setSimplePropertyBag(TKey key, Object value) {
191 if (value == null) {
192 this.internalRemoveItem(key);
193 } else {
194 // If the item was to be deleted, the deletion becomes an update.
195 if (this.removedItems.remove(key)) {
196 internalAddItemToChangeList(key, this.modifiedItems);
197 } else {
198 // If the property value was not set, we have a newly set
199 // property.
200 if (!this.containsKey(key)) {
201 internalAddItemToChangeList(key, this.addedItems);
202 } else {
203 // The last case is that we have a modified property.
204 if (!this.modifiedItems.contains(key)) {
205 internalAddItemToChangeList(key, this.modifiedItems);
206 }
207 }
208 }
209
210 this.items.put(key, value);
211 this.changed();
212 }
213 }
214
215 /**
216 * Occurs when Changed.
217 */
218 private List<IPropertyBagChangedDelegate<TKey>> onChange =
219 new ArrayList<IPropertyBagChangedDelegate<TKey>>();
220
221 /**
222 * Set event to happen when property changed.
223 *
224 * @param change change event
225 */
226 public void addOnChangeEvent(IPropertyBagChangedDelegate<TKey> change) {
227 onChange.add(change);
228 }
229
230 /**
231 * Remove the event from happening when property changed.
232 *
233 * @param change change event
234 */
235 public void removeChangeEvent(IPropertyBagChangedDelegate<TKey> change) {
236 onChange.remove(change);
237 }
238
239 /**
240 * Returns an iterator over a set of elements of type T.
241 *
242 * @return an Iterator.
243 */
244 @Override
245 public Iterator<HashMap<TKey, Object>> iterator() {
246 return (Iterator<HashMap<TKey, Object>>) this.items.keySet().iterator();
247 }
248
249 }