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}