    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}