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 024package microsoft.exchange.webservices.data.core; 025 026import microsoft.exchange.webservices.data.misc.OutParam; 027import microsoft.exchange.webservices.data.property.complex.IPropertyBagChangedDelegate; 028 029import java.util.ArrayList; 030import java.util.HashMap; 031import java.util.Iterator; 032import java.util.List; 033import java.util.Map; 034 035/** 036 * Represents a simple property bag. 037 * 038 * @param <TKey> The type of key 039 */ 040public 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. 102 * 103 * @return the added item 104 */ 105 public Iterable<TKey> getAddedItems() { 106 return this.addedItems; 107 } 108 109 /** 110 * Gets the removed item. 111 * 112 * @return the removed item 113 */ 114 public Iterable<TKey> getRemovedItems() { 115 return this.removedItems; 116 } 117 118 /** 119 * Gets the modified item. 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}