Holger's
Java API

com.antelmann.db
Class WrappedDBClassStore<T extends DBEntry>

java.lang.Object
  extended by com.antelmann.db.WrappedDBClassStore<T>
All Implemented Interfaces:
DBClassStore<T>, ProcessedFilterOption<T>, TransactionRequired, ProcessorHook<T,DatabaseException>, Wrapped<DBClassStore<T>>
Direct Known Subclasses:
ArchiveDBClassStore, DBClassStoreCache, DBDocumentStore, FriendsEntryStore, GPersonStore, ReadOnlyStore, SQLColumnInfoStore, TaggablePropertyEntrySQLStore, WrappedDBClassStoreMapping

public class WrappedDBClassStore<T extends DBEntry>
extends Object
implements DBClassStore<T>, ProcessedFilterOption<T>, ProcessorHook<T,DatabaseException>

a generic DBClassStore wrapper easing the implementation of special wrappers. In addition to make it easy to just implement some methods, there are also some convenient method implementations that provide some generally useful functionality. WrappedDBClassStore instances are also supported by AbstractDatabase.queryStoreForInterface(Class, Class), so that the interfaces of the embedded store can also be exposed via that method without having to inherit and implement and then delegate the methods for an interface.

Since:
21. Oktober 2007, 20:06
Author:
Holger Antelmann
See Also:
AbstractDatabase.queryStoreForInterface(Class, Class)

Nested Class Summary
 
Nested classes/interfaces inherited from interface com.antelmann.db.DBClassStore
DBClassStore.DBMethod
 
Field Summary
protected  DBClassStore<T> store
          access to the embedded original store; only the constructor should change this value
 
Constructor Summary
protected WrappedDBClassStore()
          when using this constructor, the embedded store must still be initialized.
  WrappedDBClassStore(DBClassStore<T> store)
           
 
Method Summary
 void add(Processor<T,? extends DatabaseException> p)
           
protected  void checkReadAccess()
          overwrite this method to further restrict read access (based on the current user for example)
protected  void checkWriteAccess()
          overwrite this method to further restrict write access (based on the current user for example)
 boolean containsID(Object id)
          determines whether the given ID is present in this store.
 int deleteEntries(Filter<? super T> filter)
          deletes all DBEntry objects that match the given filter; if the filter is null, all resources are deleted.
protected  int deleteEntriesIndividually(Filter<? super T> filter)
          deletes all applicable entries by instantiating them and then call deleteEntry(Object) on each entries.
 boolean deleteEntry(Object id)
          removes the entry with the given ID from this store in the database.
 boolean exposesInterfaces()
          if true (the default), AbstractDatabase.queryStoreForInterface(Class, Class) will expose the interfaces of the internal store
 DBEnumeration<T> fetch(Filter<? super T> filter)
          allows to retrieve the entries of this storage via iteration.
 DBEnumeration<Stub<T>> fetchStubs(Filter<? super Stub<?>> filter)
          allows to access objects from this store w/o having to instantiate the entire original objects, but instead use Stubs to be able to display the list properly for selection.
 Object generateNewID()
          this method is to generate unique new IDs for the DBEntry at hand - if the application has no other specific way of providing new IDs for this implementation.
 Filter<? super T> getAccessFilter()
           
 Filter<? super Stub<?>> getAccessStubFilter()
           
 Database<?> getDatabase()
          provides access to the database instance that also coordinates the transaction management.
 T getEntry(Object id)
          returns the DBEntry based on its ID.
 Class<T> getEntryClass()
          returns the runtime class type this store represents
 Processor<T,? extends DatabaseException> getFetchProcessor()
           
 Handler<T,? extends DatabaseException> getPreStoreHandler()
           
 Handler<T,? extends DatabaseException> getStoreHandler()
           
 Stub<T> getStub(Object id)
          returns a Stub representing the resource for the given ID or null.
 Processor<Stub<T>,? extends DatabaseException> getStubProcessor()
           
 void insert(T entry)
          it is suggested to create the entry with an ID obtained through generateNewID() before passing it into this method.
 Object insertAsNew(T entry)
          inserts the given entry using an ID generated by generateNewID while ignoring the ID of the given entry.
 boolean isApplyFilterProcessingRecursively()
           
 boolean isDeleteEntriesIndividually()
           
 boolean isEnsureTransactionsOnFetch()
           
 boolean isProcessBeforeFiltering()
          false by default; see setProcessBeforeFiltering(boolean)
<I> I
queryForInterface(Class<I> desiredInterface)
           
 boolean remove(Processor<T,? extends DatabaseException> p)
           
 void setAccessFilter(Filter<? super T> accessFilter)
          allows to provide a filter that will limit access to the content of the store in regards to all read and write operations.
 void setAccessStubFilter(Filter<? super Stub<?>> accessStubFilter)
          allows to not only filter entries themselves but also their respective stubs if applicable
 void setApplyFilterProcessingRecursively(boolean flag)
           
 void setDeleteEntriesIndividually(boolean flag)
           
 void setEnsureTransactionsOnFetch(boolean flag)
           
 void setExposesInterfaces(boolean flag)
          controls whether AbstractDatabase.queryStoreForInterface(Class, Class) should expose the interfaces of the internally embedded store
 void setFetchProcessor(Processor<T,? extends DatabaseException> fetchProcessor)
           
 void setPreStoreHandler(Handler<T,? extends DatabaseException> preStoreHandler)
           
 void setProcessBeforeFiltering(boolean flag)
          This setting only applies if the embedded store doesn't support ProcessorHook, which is preferred over using this method, because several hassles can be avoided that way (see below).
 void setProcessBeforeFiltering(boolean flag, boolean recursively)
           
 void setStoreHandler(Handler<T,? extends DatabaseException> storeHandler)
           
 void setStubProcessor(Processor<Stub<T>,? extends DatabaseException> stubProcessor)
           
 int size(Filter<? super T> filter)
          returns the total number of T elements in this store based on the given filter (which may be null)
 DBClassStore<T> unwrap()
          returns the embedded instance that this wrapper encloses
 void update(T entry)
          updates the given entry in the database.
protected
<X> Filter<X>
wrapFilterForProcessing(Filter<? super X> filter, Processor<X,? extends DatabaseException> p)
          This method is only used if setProcessBeforeFiltering(boolean) is set to true.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

store

protected DBClassStore<T extends DBEntry> store
access to the embedded original store; only the constructor should change this value

Constructor Detail

WrappedDBClassStore

protected WrappedDBClassStore()
when using this constructor, the embedded store must still be initialized. This constructor is useful if the construction of the embedded store may require more than one line of code but still wants to be enclosed within the constructor.

See Also:
store

WrappedDBClassStore

public WrappedDBClassStore(DBClassStore<T> store)
Method Detail

getDatabase

public final Database<?> getDatabase()
Description copied from interface: DBClassStore
provides access to the database instance that also coordinates the transaction management.

Specified by:
getDatabase in interface DBClassStore<T extends DBEntry>

getEntryClass

public final Class<T> getEntryClass()
Description copied from interface: DBClassStore
returns the runtime class type this store represents

Specified by:
getEntryClass in interface DBClassStore<T extends DBEntry>

unwrap

public DBClassStore<T> unwrap()
Description copied from interface: Wrapped
returns the embedded instance that this wrapper encloses

Specified by:
unwrap in interface Wrapped<DBClassStore<T extends DBEntry>>

getAccessFilter

public final Filter<? super T> getAccessFilter()
See Also:
setAccessFilter(Filter)

setAccessFilter

public void setAccessFilter(Filter<? super T> accessFilter)
allows to provide a filter that will limit access to the content of the store in regards to all read and write operations. If this filter is to be also applied for deleteEntries(Filter), the option setDeleteEntriesIndividually(boolean) should be set to true. The size(Filter) method remains unaffected.

See Also:
setAccessStubFilter(Filter)

getAccessStubFilter

public final Filter<? super Stub<?>> getAccessStubFilter()

setAccessStubFilter

public void setAccessStubFilter(Filter<? super Stub<?>> accessStubFilter)
allows to not only filter entries themselves but also their respective stubs if applicable

See Also:
setAccessFilter(Filter)

exposesInterfaces

public final boolean exposesInterfaces()
if true (the default), AbstractDatabase.queryStoreForInterface(Class, Class) will expose the interfaces of the internal store

See Also:
setExposesInterfaces(boolean)

setExposesInterfaces

public void setExposesInterfaces(boolean flag)
controls whether AbstractDatabase.queryStoreForInterface(Class, Class) should expose the interfaces of the internally embedded store


isEnsureTransactionsOnFetch

public final boolean isEnsureTransactionsOnFetch()

setEnsureTransactionsOnFetch

public void setEnsureTransactionsOnFetch(boolean flag)

isDeleteEntriesIndividually

public final boolean isDeleteEntriesIndividually()

setDeleteEntriesIndividually

public void setDeleteEntriesIndividually(boolean flag)

getFetchProcessor

public final Processor<T,? extends DatabaseException> getFetchProcessor()

setFetchProcessor

@Warning(value="depending on the settings, the processor may not run before filtering during fetch occurs")
public void setFetchProcessor(Processor<T,? extends DatabaseException> fetchProcessor)
See Also:
setProcessBeforeFiltering(boolean), ProcessorHook

getStubProcessor

public final Processor<Stub<T>,? extends DatabaseException> getStubProcessor()

setStubProcessor

@Warning(value="note that processing may influence filtering")
public void setStubProcessor(Processor<Stub<T>,? extends DatabaseException> stubProcessor)

getStoreHandler

public final Handler<T,? extends DatabaseException> getStoreHandler()

setStoreHandler

public void setStoreHandler(Handler<T,? extends DatabaseException> storeHandler)

getPreStoreHandler

public final Handler<T,? extends DatabaseException> getPreStoreHandler()

setPreStoreHandler

public void setPreStoreHandler(Handler<T,? extends DatabaseException> preStoreHandler)

containsID

public boolean containsID(Object id)
                   throws DatabaseException
Description copied from interface: DBClassStore
determines whether the given ID is present in this store.

Specified by:
containsID in interface DBClassStore<T extends DBEntry>
Throws:
DatabaseException

deleteEntry

public boolean deleteEntry(Object id)
                    throws DatabaseException
Description copied from interface: DBClassStore
removes the entry with the given ID from this store in the database.

Specified by:
deleteEntry in interface DBClassStore<T extends DBEntry>
Returns:
true only if the DBEntry with the given ID was actually found and deleted.
Throws:
DatabaseException

deleteEntries

public int deleteEntries(Filter<? super T> filter)
                  throws DatabaseException
Description copied from interface: DBClassStore
deletes all DBEntry objects that match the given filter; if the filter is null, all resources are deleted. Calling this method does not necessarily entail that DBClassStore.deleteEntry(Object) is called for each entry passing the filter (although stores may choose to do so)! Consequently, if a store's implementation does not call DBClassStore.deleteEntry(Object) on each instance, calling this method may result in changes that are hard to monitor for versioning purposes.

Specified by:
deleteEntries in interface DBClassStore<T extends DBEntry>
Returns:
the number of objects that were deleted
Throws:
DatabaseException
See Also:
setProcessBeforeFiltering(boolean)

deleteEntriesIndividually

protected int deleteEntriesIndividually(Filter<? super T> filter)
                                 throws DatabaseException
deletes all applicable entries by instantiating them and then call deleteEntry(Object) on each entries.

Throws:
DatabaseException

generateNewID

public Object generateNewID()
                     throws DatabaseException,
                            UnsupportedOperationException
Description copied from interface: DBClassStore
this method is to generate unique new IDs for the DBEntry at hand - if the application has no other specific way of providing new IDs for this implementation. Note that not every implementation may embrace this method of providing DBEntry IDs; but this method may be preferred if the ID is merely to distinguish the Resources in the database (rather than being derived for another purpose as well). Not every call must necessarily return a new value, but it must return an ID not yet present in the persistent storage. In particular, an unused ID (i.e. returned earlier for creating an object, but that object was never inserted and committed into the database) may be returned again in a subsequent call in another transaction. Within one transaction, however, the returned ID must be different on each call. As a returned ID may not be actually be used, it would be unwise to rely on the return value to generate IDs that are required to provide for consecutive counters. An implementing class should document the exact behavior, so that the implications of usage are clear for that specific class - as they may be different (sometimes, each call to this method generates a unique value, sometimes that is only guaranteed within the same transaction). Generally, it is advisable, to always create unique IDs that are valid over transaction boundaries.

Specified by:
generateNewID in interface DBClassStore<T extends DBEntry>
Throws:
DatabaseException
UnsupportedOperationException
See Also:
SessionIdGenerator, DBEntry.getID()

insert

public void insert(T entry)
            throws DatabaseException
Description copied from interface: DBClassStore
it is suggested to create the entry with an ID obtained through generateNewID() before passing it into this method. The ID of the entry must not already exist in the database.

Specified by:
insert in interface DBClassStore<T extends DBEntry>
Throws:
DatabaseException
See Also:
DBClassStore.generateNewID()

insertAsNew

public Object insertAsNew(T entry)
                   throws DatabaseException,
                          UnsupportedOperationException
Description copied from interface: DBClassStore
inserts the given entry using an ID generated by generateNewID while ignoring the ID of the given entry. With this method, the same Object (with the same ID) can be inserted multiple times, stored with a new ID on each call; the ID creation is handled automatically. This is an optional feature that might not be implemented in all cases.

Specified by:
insertAsNew in interface DBClassStore<T extends DBEntry>
Returns:
the newly created ID of the object used as ID for the given entry to be inserted
Throws:
DatabaseException
UnsupportedOperationException
See Also:
DBEntry.getID(), DBClassStore.generateNewID()

update

public void update(T entry)
            throws DatabaseException
Description copied from interface: DBClassStore
updates the given entry in the database.

Specified by:
update in interface DBClassStore<T extends DBEntry>
Throws:
DatabaseException - if the database was not able to perform the update or it the entry didn't exist in the database before calling this method

isProcessBeforeFiltering

public final boolean isProcessBeforeFiltering()
false by default; see setProcessBeforeFiltering(boolean)

Specified by:
isProcessBeforeFiltering in interface ProcessedFilterOption<T extends DBEntry>

setProcessBeforeFiltering

public void setProcessBeforeFiltering(boolean flag)
This setting only applies if the embedded store doesn't support ProcessorHook, which is preferred over using this method, because several hassles can be avoided that way (see below). By default, this option is set to false. As a result, entries/stubs are not processed when running through a filter during fetch operations. Unfortunately, setting this option to true has a few other drawbacks! First, a given CascadingFilter is actually altered when used for fetching, so you better must not reuse such a filter passed to the store interface. Second, a processor that returns another object than the one given will lead to the processed object to not be returned by the DBEnumeration anymore in case of a fetch. Third, Problems may arise if a store implementation calls the filter twice on the same instance; because in this case, the processor is called multiple times on the same entry - which may or may not be a problem based on the processor's implementation (other than just performance). Another problem may arise with special filters where the accept method is never actually called by the implementation. Last but not least in the line of problems: DatabaseExceptions thrown during processing are masked as RuntimeExceptions within the accept-method of the filter.

Specified by:
setProcessBeforeFiltering in interface ProcessedFilterOption<T extends DBEntry>
See Also:
wrapFilterForProcessing(Filter, Processor), setProcessBeforeFiltering(boolean, boolean), isApplyFilterProcessingRecursively()

setProcessBeforeFiltering

public void setProcessBeforeFiltering(boolean flag,
                                      boolean recursively)

isApplyFilterProcessingRecursively

public final boolean isApplyFilterProcessingRecursively()

setApplyFilterProcessingRecursively

public void setApplyFilterProcessingRecursively(boolean flag)

fetch

@Warning(value="depending on processBeforeFiltering, filter may either be altered or entry may not be processed before filtering")
public DBEnumeration<T> fetch(Filter<? super T> filter)
                                       throws DatabaseException
Description copied from interface: DBClassStore
allows to retrieve the entries of this storage via iteration. Note that the order of the entries is undefined, unless a specially designed filter hints a sorting order to an implementing class that additionally supports sorting.

As all relevant entries may not completely fit into memory, an Enumeration is returned instead of a list. To directly get all entries as a list (and thus avoid concurrency problems), consider using methods from AbstractIterator to quickly retrieve all resources before processing them.

Be aware that the result of the enumeration may become undefined if data is inserted/deleted/updated while the elements are accessed. To guarantee consistency, all access to the returned Enumeration must be externally synchronized by holding the monitor of the database transaction throughout maintaining the Enumeration.

Note that you may have IterationExceptions being thrown on calling methods on the returned Enumeration, which are caused by either DatabaseExceptions or InstantiationExceptions on trying to fetch the next element, as not all possible errors may be caught on calling this method (as it possibly cannot instantiate all entries in advance).

All access to the returned Enumeration must be made within an active transaction.

As the returned Enumeration may hold resources to the database while iterating, the caller must ensure that these resources can be properly release. This is usually achieved by simply completely iterating through the return value, in which case the DBEnumeration is expected to properly clean up automatically. But in cases where the caller doesn't intend to go all the way through the Enumeration, the caller has to clean up explicitly, which can be done by calling the close() method on the returned DBEnumeration.

Specified by:
fetch in interface DBClassStore<T extends DBEntry>
Parameters:
filter - may be null, in which case all entries from are returned.
Throws:
DatabaseException
See Also:
setProcessBeforeFiltering(boolean)

fetchStubs

@Warning(value="depending on processBeforeFiltering, filter may either be altered or entry may not be processed before filtering")
public DBEnumeration<Stub<T>> fetchStubs(Filter<? super Stub<?>> filter)
                                                  throws DatabaseException
Description copied from interface: DBClassStore
allows to access objects from this store w/o having to instantiate the entire original objects, but instead use Stubs to be able to display the list properly for selection. The given filter may be null. Other than that, the same transactional implications apply as for fetch(Filter).

Specified by:
fetchStubs in interface DBClassStore<T extends DBEntry>
Throws:
DatabaseException
See Also:
setProcessBeforeFiltering(boolean)

wrapFilterForProcessing

@Todo(value="find a solution that does not require altering the given filter but still allows for recognition of special filters and also takes care of a processor that may return a different object identity")
@Warning(value="filter may be altered as a result of embedding processing")
protected <X> Filter<X> wrapFilterForProcessing(Filter<? super X> filter,
                                                                       Processor<X,? extends DatabaseException> p)
This method is only used if setProcessBeforeFiltering(boolean) is set to true. In case of a CascadingFilter, this implementation places the processing into an inner filter, so that special filters (that must inherit from CascadingFilter of course) can still be recognized by the embedded store's implementation for special performance optimization options; as a nasty side-effect, the given filter is consequently altered and is better not to be used hereafter.

Parameters:
filter - the original filter
See Also:
setProcessBeforeFiltering(boolean), fetch(Filter), fetchStubs(Filter), deleteEntries(Filter), size(Filter), CascadingFilter

getEntry

public T getEntry(Object id)
                           throws DatabaseException
Description copied from interface: DBClassStore
returns the DBEntry based on its ID.

Specified by:
getEntry in interface DBClassStore<T extends DBEntry>
Parameters:
id - the ID that is retrieved from Resource.getID()
Returns:
the associated DBEntry or null if the id is unknown
Throws:
DatabaseException
See Also:
DBEntry.getID()

getStub

public Stub<T> getStub(Object id)
                                throws DatabaseException
Description copied from interface: DBClassStore
returns a Stub representing the resource for the given ID or null. This method allows to display the object w/o having to retrieve the full DBEntry.

Specified by:
getStub in interface DBClassStore<T extends DBEntry>
Throws:
DatabaseException

size

public int size(Filter<? super T> filter)
         throws DatabaseException
Description copied from interface: DBClassStore
returns the total number of T elements in this store based on the given filter (which may be null)

Specified by:
size in interface DBClassStore<T extends DBEntry>
Parameters:
filter - if non-null, only those elements will be counted that are applicable to the filter
Throws:
DatabaseException
See Also:
setProcessBeforeFiltering(boolean)

queryForInterface

public <I> I queryForInterface(Class<I> desiredInterface)
See Also:
AbstractDatabase.queryStoreForInterface(Class, Class)

checkReadAccess

protected void checkReadAccess()
                        throws DBAccessDeniedWarning
overwrite this method to further restrict read access (based on the current user for example)

Throws:
DBAccessDeniedWarning

checkWriteAccess

protected void checkWriteAccess()
                         throws DBAccessDeniedWarning
overwrite this method to further restrict write access (based on the current user for example)

Throws:
DBAccessDeniedWarning

add

public void add(Processor<T,? extends DatabaseException> p)
Specified by:
add in interface ProcessorHook<T extends DBEntry,DatabaseException>

remove

public boolean remove(Processor<T,? extends DatabaseException> p)
Specified by:
remove in interface ProcessorHook<T extends DBEntry,DatabaseException>


(c) Holger Antelmann since 2001- all rights reserved (contact: info@antelmann.com)
see www.antelmann.com/developer for further details and available downloads