001package com.hammurapi.store; 002 003import java.util.Comparator; 004import java.util.Iterator; 005import java.util.concurrent.locks.ReadWriteLock; 006 007import com.hammurapi.extract.Extractor; 008import com.hammurapi.extract.Predicate; 009 010/** 011 * Abstraction of object store. 012 * @author Pavel Vlasov. 013 * 014 * @param <T> Object type. 015 * @param <PK> Primary key type. 016 * @param <S> Self-type - sub-type of store. Generic parameter for predicates, extractors, update tasks and views. 017 */ 018public interface Store<T, PK, S extends Store<T,PK,S>> extends ReadWriteLock, Iterable<T> { 019 020 enum ViewType { 021 /** 022 * Live perform all operations on the master data, they 023 * do not create an intermediary store for view data. 024 */ 025 LIVE, 026 /** 027 * Lazy views create intermediary store which contains only 028 * data visible by the view. Updates from the main store 029 * are queued up and get applied to the intermediary store when 030 * one of view data retrieval methods is invoked. 031 */ 032 LAZY, 033 /** 034 * Asynchronous views create intermediary store which contains only 035 * data visible by the view. Updates from the main store 036 * are queued up and get applied to the intermediary store in a 037 * background task, or when 038 * one of view data retrieval methods is invoked. 039 */ 040 ASYNCHRONOUS, 041 /** 042 * Synchronous views create intermediary store which contains only 043 * data visible by the view. Updates from the main store 044 * get applied to the view store as part of update operation. 045 */ 046 SYNCHRONOUS 047 } 048 049 /** 050 * Object handle. 051 * @author Pavel Vlasov 052 * 053 * @param <T> 054 */ 055 interface Handle<T, PK, S extends Store<T,PK,S>> { 056 057 /** 058 * Updates object referenced by this handle. Clears cache and updates 059 * indexes. The new object shall have the same primary key if the store 060 * has primary key extractor. 061 * @param obj New object for the handle (for immutable objects). 062 */ 063 void update(T obj); 064 065 /** 066 * Clears cache and updates 067 * indexes. Updated object shall have the same primary key if the store 068 * has primary key extractor. 069 */ 070 void update(); 071 072 /** 073 * Removes object referenced by this handle. 074 */ 075 void remove(); 076 077 /** 078 * @return Object referenced by this handle. 079 */ 080 T get(); 081 082 /** 083 * @return Primary key if object store is configured with primary 084 * key extractor. 085 */ 086 PK getPrimaryKey(); 087 088 /** 089 * @return True if object referenced by this handle is present in the store. 090 */ 091 boolean isValid(); 092 093 /** 094 * Extracts value from handle's object using given extractor 095 * and internal handle's cache. 096 * @param <V> Value type 097 * @param extractor Extractor 098 * @return extracted value. 099 */ 100 <V> V extract(Extractor<T, V, S> extractor); 101 } 102 103 // CRUDI 104 105 /** 106 * Puts object to the store. 107 * If object is already present in the store, it gets 108 * updated in the store. 109 * @param obj Object to put to the store. 110 * @param validators Predicate(s) which are checked when object is retrieved from the store. 111 * If there is more than one predicate, predicates are connected with AND. If validator(s) evaluate to 112 * false, the object handle is considered invalid, i.e. object is considered removed from the store. 113 * Once validator(s) evaluate to false, they shall always evaluate to false. One of use of validators 114 * can be to expire object in the store, i.e. after some time validator returns false and object is cleared 115 * from the database. If validators evaluate to false at put time, object is not put to the store and 116 * put() returns null. Validators evaluation result is not cached. 117 * @return Object handle or null if validator(s) evaluate to false. 118 */ 119 Handle<T, PK, S> put(T obj, Predicate<T, S>... validators); 120 121 /** 122 * Retrieves all objects from the store. 123 * @return 124 */ 125 Iterable<T> getAll(); 126 127 /** 128 * Processes all objects in the store. 129 * @param processor 130 * @return number of object queried. 131 */ 132 int queryAll(QueryTask<T, PK, S> processor); 133 134 /** 135 * Retrieves object with given primary key. 136 * @param primaryKey 137 * @return 138 * @throws IllegalStateException if object store is configured without 139 * primary key. 140 */ 141 T getByPrimaryKey(PK primaryKey); 142 143 /** 144 * Some stores may return StoreIterator, which 145 * needs to be closed if iterator operation is 146 * terminated before hasNext() returns false. 147 * @author Pavel Vlasov. 148 * 149 * @param <T> 150 */ 151 interface StoreIterator<T> extends Iterator<T> { 152 void close(); 153 } 154 155 /** 156 * Retrieves objects matching the predicate. 157 * @param selector 158 * @return 159 */ 160 Iterable<T> get(Predicate<T, S> selector); 161 162 /** 163 * Processes objects matching the predicate. 164 * @param selector 165 * @return Number of objects queried. 166 */ 167 int query(Predicate<T, S> selector, QueryTask<T, PK, S> processor); 168 169 /** 170 * Processes values extracted from objects matching the predicate. 171 * @param selector 172 * @param extractor Extractor. 173 * @param processor Processor of query results. 174 * @return Number of objects queried. 175 */ 176 <V> int query(Predicate<T, S> selector, Extractor<T, V, S> extractor, QueryTask<V, PK, S> processor); 177 178 /** 179 * Processes multiple values extracted from objects matching the predicate. 180 * @param selector Objects shall match this predicate. If null, all objects match. 181 * @param extractor Extractor 182 * @param valueSelector Values from matched objects shall match this predicate. If null, all values match. 183 * Value selectors are executed in separate tasks from extractor. 184 * Separation of value selection logic from value extraction logic makes 185 * sense if value selection logic is relatively heavy and parallelization of its 186 * execution will reduce overall query execution time. 187 * @param processor Processor of query results. 188 * @return Number of objects queried. 189 */ 190 <V> int queryMultiple(Predicate<T, S> selector, Extractor<T, Iterable<V>, S> extractor, Predicate<V, S> valueSelector, QueryTask<V, PK, S> processor); 191 192 /** 193 * Retrieves values from objects matching the predicate. 194 * @param <V> 195 * @param selector Object selector. 196 * @param extractor Value extractor. If null, then object itself is returned. 197 * @param ordered If true, then returned result is ordered by comparator or by natural order if 198 * comparator is null. 199 * @param comparator Comparator to use for ordering. 200 * @return 201 */ 202 <V> Iterable<V> get(Predicate<T, S> selector, Extractor<T, V, S> extractor, boolean ordered, Comparator<V> comparator); 203 204 /** 205 * Retrieves values from objects matching the predicate. Multiple values are retrieved from each object. 206 * @param <V> 207 * @param selector Objects shall match this predicate. If null, all objects match. 208 * @param extractor Value extractor. 209 * @param valueSelector Values from matched objects shall match this predicate. If null, all values match. 210 * Value selectors are executed in separate tasks from extractor. 211 * Separation of value selection logic from value extraction logic makes 212 * sense if value selection logic is relatively heavy and parallelization of its 213 * execution will reduce overall query execution time. 214 * @param ordered If true, then returned result is ordered by comparator or by natural order if 215 * comparator is null. 216 * @param comparator Comparator to use for ordering. 217 * @return 218 */ 219 <V> Iterable<V> getMultiple(Predicate<T, S> selector, Extractor<T, Iterable<V>, S> extractor, Predicate<V, S> valueSelector, boolean ordered, Comparator<V> comparator); 220 221 /** 222 * Removes all entries from the store. 223 */ 224 void clear(); 225 226 /** 227 * Removes specified object from the store. 228 * @param obj Object to remove. 229 * @return true if object was removed. 230 */ 231 boolean remove(T obj); 232 233 /** 234 * Removes object by primary key. 235 * @param primaryKey 236 * @return 237 */ 238 boolean removeByPrimaryKey(PK primaryKey); 239 240 /** 241 * Removes objects matching the predicate. 242 * @param predicate 243 * @return number of returned objects or -1 if number is unknown. 244 */ 245 int remove(Predicate<T, S> selector); 246 247 248 /** 249 * Task to update objects. 250 * @author Pavel Vlasov. 251 * 252 * @param <T> Object type. 253 */ 254 interface UpdateTask<T, PK, S extends Store<T,PK,S>> { 255 256 /** 257 * Executes update. 258 * @param store Store to perform joins, sub-queries, etc. 259 * @param obj 260 * @param primaryKey 261 * @return Undo task to rollback changes done by this task or null if there are no changes. 262 */ 263 Runnable execute(S store, Handle<T,PK,S> handle); 264 } 265 266 /** 267 * Task to perform processing on objects (without updating). 268 * @author Pavel Vlasov. 269 * 270 * @param <T> Object type. 271 */ 272 interface QueryTask<T, PK, S extends Store<?,PK,S>> { 273 274 /** 275 * Performs querying. 276 * @param store Store to perform joins, sub-queries, etc. 277 * @param obj 278 * @param primaryKey 279 */ 280 void execute(S store, T obj, PK primaryKey); 281 } 282 283 /** 284 * Updates objects matching the predicate. 285 * @param selector 286 * @param updater 287 * @return 288 */ 289 int update(Predicate<T, S> selector, UpdateTask<T, PK, S> updater); 290 291 /** 292 * Adds index to the store to speed-up extraction operations. 293 * @param predicate Only store items matching the predicate are indexed. 294 * @param extractor Extractor of the index key. 295 * @param Index type. 296 * @param ordered If true index is ordered. 297 * @param comparator Comparator to use for ordering. If null, then natural order is used. 298 * @return A "mix" of Index sub-interfaces corresponding to the 299 * @param <V> Value type extracted by extractor for ordering. 300 * @param <ST> Type of index elements, which can be a sub-type of store element type. 301 * index creation parameters. 302 */ 303 <V, ST extends T> Index<T,ST,PK,V,S> addIndex( 304 Predicate<T, S> predicate, 305 Extractor<ST, V, S> extractor, 306 Index.Type type, 307 boolean ordered, 308 Comparator<V> comparator); 309 310 /** 311 * If primary key is set, then the store shall use equals on the 312 * value returned from the primaryKeyExtractor 313 * instead of equals on the object to compare objects for removal and update (put). 314 * @param primaryKeyExtractor Primary key extractor. 315 * @throws IllegalStateException If primary key is already set. 316 */ 317 Extractor<T, PK, S> getPrimaryKeyExtractor(); 318 319 /** 320 * Creates a view - a store which sees only objects matching the given selector. 321 * @param selector View selector. 322 * @param materialized If true, view elements are calculated at modify time instead of query time. 323 * @return Store which sees only objects matching give selector. The returned store is backed by the master store. 324 */ 325 S createView(Predicate<T, S> selector, ViewType viewType); 326 327 /** 328 * Creates unmodifiable facade for this store. 329 * @return 330 */ 331 S createUnmodifiableFacade(); 332 333}