1 19 package org.netbeans.mdr.persistence.memoryimpl; 20 21 import org.netbeans.mdr.persistence.*; 22 import java.util.*; 23 import java.io.*; 24 25 import org.netbeans.mdr.util.*; 26 27 35 public abstract class MultivaluedIndexImpl implements MultivaluedIndex, Streamable { 36 37 38 39 40 41 protected String name; 42 protected Storage.EntryType keyType; 43 protected Storage.EntryType valueType; 44 protected boolean unique; 45 protected Map entries; 46 protected StorageImpl storage; 47 48 protected MultivalueLog transLog = new MultivalueLog (this); 49 50 51 52 53 54 55 public MultivaluedIndexImpl(String name, StorageImpl storage, Storage.EntryType keyType, Storage.EntryType valueType, boolean unique) { 56 this.name = name; 57 this.keyType = keyType; 58 this.valueType = valueType; 59 this.unique = unique; 60 this.storage = storage; 61 entries = new HashMap(); 62 } 63 64 65 public MultivaluedIndexImpl() { 66 } 67 68 69 70 71 72 public String getName() throws StorageException { 73 return this.name; 74 } 75 76 public Storage.EntryType getValueType() throws StorageException { 77 return this.valueType; 78 } 79 80 public Storage.EntryType getKeyType() throws StorageException { 81 return this.keyType; 82 } 83 84 public synchronized boolean remove(Object key) throws StorageException { 85 Object value = entries.remove(key); 86 if (value != null) { 87 transLog.logRemoveKey(key, value); 88 return true; 89 } else 90 return false; 91 } 92 93 public synchronized java.util.Set keySet() throws StorageException { 94 return entries.keySet(); 95 } 96 97 100 public synchronized void add(Object key,Object value) throws StorageException { 101 Collection vals = (Collection) entries.get (key); 102 if (vals == null) { 103 vals = new ArrayList (); 104 entries.put(key, vals); 105 } else if (unique && vals.contains(value)) { 106 throw createValueAlreadyContainedExc(key, value); 107 } 108 vals.add(value); 109 transLog.logAdd(key, value); 110 } 111 112 113 114 115 116 public boolean isUnique() throws StorageException { 117 return unique; 118 } 119 120 public synchronized java.util.Collection getItems(Object key) throws StorageException { 121 Collection vals = (Collection) entries.get(key); 122 if (vals == null) { 123 vals = new ArrayList(); 124 entries.put(key, vals); 125 } 126 return new MIWrapper((List) vals, key); 127 } 128 129 public synchronized java.util.Collection getObjects(Object key, SinglevaluedIndex s) throws StorageException { 130 if (keyType == Storage.EntryType.MOFID) { 131 return new MOWrapper((List) getItems(key), s, key); 132 } else { 133 return getItems(key); 134 } 135 } 136 137 140 public synchronized boolean remove(Object key,Object value) throws StorageException { 141 Collection vals = (Collection) entries.get (key); 142 if (vals != null && vals.remove(value)) { 143 transLog.logRemove(key, value); 144 return true; 145 } else { 146 return false; 147 } 148 } 149 150 151 152 153 154 160 public void write(java.io.OutputStream out) throws StorageException { 161 try { 162 IOUtils.writeString(out, name); 163 out.write(keyType.encode()); 164 out.write(valueType.encode()); 165 Utils.write(out, entries, storage); 166 } catch (java.io.IOException e) { 167 throw new StorageIOException(e); 168 } 169 } 170 174 public void read(java.io.InputStream is) throws StorageException { 175 try { 176 name = IOUtils.readString(is); 177 keyType = Storage.EntryType.decodeEntryType((byte) is.read()); 178 valueType = Storage.EntryType.decodeEntryType((byte) is.read()); 179 entries = (Map) Utils.read(is, storage); 180 } catch (java.io.IOException e) { 181 throw new StorageIOException(e); 182 } 183 } 184 185 188 public synchronized Collection queryByKeyPrefix (Object prefix, SinglevaluedIndex primaryIndex) throws StorageException { 189 if (keyType != Storage.EntryType.STRING) { 190 throw new UnsupportedOperationException ("Key type must be EntryType.STRING"); 191 } 192 if (!(prefix instanceof String )) { 193 throw new StorageBadRequestException ("String object parameter expected."); 194 } 195 196 List result = new LinkedList (); 197 Iterator iter = entries.keySet().iterator (); 198 while (iter.hasNext ()) { 199 String key = (String ) iter.next (); 200 if (key.startsWith ((String ) prefix)) { 201 result.add (new MapEntryImpl (key, getObjects (key, primaryIndex))); 202 } 203 } 204 return result; 205 } 206 207 208 209 210 211 protected synchronized void rollBackChanges () throws StorageException { 212 transLog.rollBack (); 213 transLog.clear (); 214 } 215 216 protected synchronized void commitChanges () throws StorageException { 217 transLog.clear (); 218 } 219 220 221 222 223 224 protected static boolean isUniqueValue(List list, Object value, int index) { 225 Iterator iter = list.iterator(); 226 for (int x = 0; iter.hasNext(); x++) { 227 Object obj = iter.next(); 228 if (x == index) 229 continue; 230 if (value.equals(obj)) 231 return false; 232 } 233 return true; 234 } 235 236 protected StorageBadRequestException createValueAlreadyContainedExc(Object key, Object value) { 237 return new StorageBadRequestException("Unique index already contains value " + value + " for key " + key); 238 } 239 240 public void changed(Object key) { 241 } 242 243 void setKey(Object key, Object vals) { 244 entries.put(key, vals); 245 } 246 247 private class MIWrapper extends AbstractList { 248 private final List inner; 249 private final Object key; 250 251 public MIWrapper(List inner, Object key) { 252 this.inner = inner; 253 this.key = key; 254 } 255 256 public Object get(int param) { 257 synchronized (MultivaluedIndexImpl.this) { 258 return inner.get(param); 259 } 260 } 261 262 public int size() { 263 synchronized (MultivaluedIndexImpl.this) { 264 return inner.size(); 265 } 266 } 267 268 public Object set(int index, Object element) { 269 synchronized (MultivaluedIndexImpl.this) { 270 Object orig; 271 if (unique && !isUniqueValue(inner, element, index)) { 272 throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element)); 273 } 274 if ((orig = inner.set(index, element)) != null) { 275 transLog.logReplace(key, orig, index); 276 } 277 return orig; 278 } 279 } 280 281 public void add(int index, Object element) { 282 synchronized (MultivaluedIndexImpl.this) { 283 if (unique && inner.contains(element)) { 284 throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element)); 285 } 286 inner.add(index, element); 287 transLog.logAdd(key, element, index); 288 } 289 } 290 291 public Object remove(int index) { 292 synchronized (MultivaluedIndexImpl.this) { 293 Object orig; 294 if ((orig = inner.remove(index)) != null) { 295 transLog.logRemove(key, orig, index); 296 return orig; 297 } else { 298 return null; 299 } 300 } 301 } 302 } 303 304 private class MOWrapper extends AbstractList { 305 private final List inner; 306 private final SinglevaluedIndex pi; 307 private final Object key; 308 309 public MOWrapper(List inner, SinglevaluedIndex pi, Object key) { 310 this.inner = inner; 311 this.pi = pi; 312 this.key = key; 313 } 314 315 public Object get(int param) { 316 try { 317 return pi.get(inner.get(param)); 318 } catch (StorageException e) { 319 throw (RuntimeException ) Logger.getDefault().annotate(new RuntimeException (), e); 320 } 321 } 322 323 public int size() { 324 synchronized (MultivaluedIndexImpl.this) { 325 return inner.size(); 326 } 327 } 328 329 public Object set(int index, Object element) { 330 if (element instanceof MOFID) { 331 if (unique && !isUniqueValue(inner, element, index)) { 332 throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element)); 333 } 334 return inner.set(index, element); 335 } else { 336 throw new IllegalArgumentException (); 337 } 338 } 339 340 public void add(int index, Object element) { 341 if (element instanceof MOFID) { 342 if (unique && inner.contains(element)) { 343 throw new RuntimeStorageException(createValueAlreadyContainedExc(key, element)); 344 } 345 inner.add(index, element); 346 } else { 347 throw new IllegalArgumentException (); 348 } 349 } 350 351 public Object remove(int index) { 352 return inner.remove(index); 353 } 354 } 355 } 356 | Popular Tags |