com.waveset.object
Class ObjectCache

java.lang.Object
  extended bycom.waveset.util.AbstractXmlObject
      extended bycom.waveset.object.ObjectCache
All Implemented Interfaces:
javax.naming.Referenceable, XmlObject

public class ObjectCache
extends AbstractXmlObject

See Also:
ObjectRef, ObjectHandle, A class that maintains a cache of objects fetched from a storage manager such as the Repository, and provides mechanisms for resolving references between objects.

The combination of the classes PersistentObject, ObjectHandle, ObjectRef, and ObjectCache gives us what amounts to a low-grade object database.

All PersistentObjects objects may contain unresolved references to other objects. As accessor methods are called on objects, the methods may decide to resolve these references by searching for them in a cache, and optionally loading them from a storage manager if they aren't in the cache. In object databases, this is often called "swizzling".

References from one object to another are represented using an ObjectRef object. In the unresolved state, an ObjectRef will contain the identity of the object, but the object itself may not be in memory. When an ObjectRef is resolved, it will point to an ObjectHandle managed by an ObjectCache.

The ObjectHandle sits between the ObjectRef and the PersistentObject so that the cache can automatically update references to new versions of an object that are placed in the cache, without having to track and update all references. ObjectHandles will be maintained by the cache should be invisible to to applications.

An ObjectHandle is quite similar to an ObjectRef, but the ObjectRef is owned by the referencing object, the ObjectHandle is owned by the cache.

Resolution of references normally happens automatically and does not need to be visible to applications. To perform automatic resolution, an object must first have a pointer to an ObjectCache. This may be set by either placing the object "in" the cache with the ObjectCache.addObject method, or by assigning a cache pointer to the object without placing it in the cache.

Next, the object with references must implement two sets of accessor methods: one to access the ObjectRef objects without resolution, and another that calls methods on the cache to perform the resolution, and return the resolved objects. Applications always call the second set of methods.

We abstract the external storage manager for objects in the ObjectLoader interface. When a reference is resolved, that doesn't exist in the cache, we will ask our associated ObjectLoader for the object. This is done so that the cache can be used in a variety of contexts, and not be wired into a particular type of storage manager.

Among the storage managers currently being used are:

  1. com.waveset.session.LocalSession - maintains a session cache for objects authorized for a particular user.
  2. com.waveset.server.Server - maintains a server cache for all objects in the repository.
Other loader types may be possible as we evolve tools that run outside of the Waveset server environment, notably the exchange file extractor.

Nested Class Summary
static class ObjectCache.CacheReport
           
 
Field Summary
static java.lang.String code_id
           
static java.lang.String ELEMENT
          Our XML element name.
 
Fields inherited from class com.waveset.util.AbstractXmlObject
_trace
 
Constructor Summary
ObjectCache()
          Build an object cache that cannot dynamically load objects.
ObjectCache(ObjectLoader loader)
          Build an object cache that can dynamically load objects.
 
Method Summary
 void addObject(PersistentObject o)
          Add an object to the cache, replacing the current version of the object if one exists.
 void addObjects(java.util.Collection objects)
          Add a collection of objects to the cache.
 void addPath(ObjectGroup org)
           
 void clear()
          Remove all objects from the cache.
 void clearObjects()
          Remove all resolved objects, but preserves the handles.
 void clearObjects(Type type)
          Remove all resolved objects of a particular type, but preserves the handles.
 void clearSuppressedTypes()
          Clear the suppression option for all types, allowing them to be in the cache.
 void decacheObject(PersistentObject obj)
          Remove an object from the cache, but leave the handle.
 void decacheObject(Type type, java.lang.String id)
          Decache an object.
 void deleteObject(PersistentObject obj)
          Remove an object and its handle from the cache.
 void deleteObject(Type type, java.lang.String id)
          Remove an object and its handle from the cache.
 void exportObjectFile(java.lang.String filename)
          Serialize the cache to a file.
 PersistentObject findObject(Type type, java.lang.String id)
          Search for an object in the cache, but do not load it if it does not exist.
 java.util.List getAdmins()
          Helper method that returns a filtered list of WSUsers that have one or more capabilities (are members of one or more AdminGroups) and control one or more Organizations (ObjectGroups), or are assigned one or more AdminRoles.
 java.util.ArrayList getAllObjects(Type type)
          Return a list of objects of a given type including subtypes.
 java.util.ArrayList getAllObjects(Type type, AttributeCondition[] attrConds)
          Return a list of objects of a given type including subtypes, qualified by an array of attribute conditions.
 java.util.ArrayList getAllObjects(Type type, WSAttributes atts)
          Return a list of objects of a given type including subtypes, qualified by a collection of attributes.
 java.util.ArrayList getCachedObjects(Type type)
          Return a list of objects currently in the cache, that have a certain type.
 java.util.ArrayList getCachedObjects(Type type, AttributeCondition[] attrConds)
          Return a list of objects currently in the cache, that have a certain type and meet certain attribute conditions.
 java.util.ArrayList getCachedObjects(Type type, WSAttributes atts)
          Return a list of objects currently in the cache, that have a certain type and attributes.
 java.lang.String getElementName()
          Return the name of our XML element, required by XmlObject.
protected  com.waveset.object.ObjectHandle getHandle(PersistentObject o)
          Retreive or create a handle for this object in the cache.
 PersistentObject getObject(Type type, java.lang.String id)
          Search for an object in the cache, and dynamically load it if it isn't yet resident.
 PersistentObject getObject(Type type, java.lang.String id, java.util.Map options)
          Object accessor that supports a map of options like LighthouseContext.
 PersistentObject getObject(Type type, java.lang.String name, java.lang.String id)
          Get an object by name or id, preferring id.
 PersistentObject getObjectIfExists(Type type, java.lang.String id)
          Search for an object in the cache, and dynamically load it if it isn't yet resident.
 PersistentObject getObjectIfExists(Type type, java.lang.String id, java.util.Map options)
          Object accessor that supports a map of options like LighthouseContext.
 java.util.ArrayList getObjects(Type type)
          Return a list of objects of a given type.
 java.util.ArrayList getObjects(Type type, AttributeCondition[] attrConds)
          Return a list of objects of a given type, qualified by an array of attribute conditions.
 java.util.ArrayList getObjects(Type type, java.util.List attrConds)
          Return a list of objects of a given type, qualified by an array of attribute conditions.
 java.util.ArrayList getObjects(Type type, WSAttributes atts)
          Return a list of objects of a given type, qualified by a collection of attributes.
 PersistentObject getObjectWithSubtypes(Type type, java.lang.String id)
          Look for an object whose type may be a subtype of the given type.
 PersistentObject getObjectWithSubtypesIfExists(Type type, java.lang.String id)
          Look for a an object in the cache, for a type that may define subtypes.
 void handlePossibleRename(Type type, java.lang.String id, java.lang.String newName)
          Handles the case of an object being possibly renamed.
 void importObjectFile(java.lang.String filename)
          Import a file of object definitions into the cache.
 void importObjects(java.lang.String xml)
          Import a file of objects into the cache.
static boolean isDefaultSuppressedType(Type t)
          Test to see if a type is by default suppressed.
 boolean isSuppressedType(Type t)
          Test to see if a type is being suppressed.
 void parseXml(org.w3c.dom.Element e)
          Deserialization method used by importObjects, and also now required by XmlObject.
 PersistentObject resolve(ObjectRef ref)
          Resolve a single reference through this cache.
 void setCheckNullIds(boolean check)
          Set a flag that causes warning messages to be displayed if an object with no ID is added to the cache.
 void setNegativeCachedTypes(Type[] types)
          Sets the list of types for which we perform negative caching - that is, we track object's which don't exist and don't hit the repository to query to see if they exist.
 void setSuppressedTypes(Type[] types)
          Specifies a list of types that are to be kept out of the cache.
 void toXml(java.lang.StringBuffer b, int indent)
          Serialize the entire cache contents, to a string buffer.
 void validate()
          Run some validation rules over the cache.
 
Methods inherited from class com.waveset.util.AbstractXmlObject
addXmlHeader, cloneObject, dump, dumpFile, getReference, println, setTrace, toIdentityString, toVerboseString, toVerboseString, toXml, toXml, toXml
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

code_id

public static final java.lang.String code_id
See Also:
Constant Field Values

ELEMENT

public static final java.lang.String ELEMENT
Our XML element name.

See Also:
Constant Field Values
Constructor Detail

ObjectCache

public ObjectCache()
Build an object cache that cannot dynamically load objects.


ObjectCache

public ObjectCache(ObjectLoader loader)
Build an object cache that can dynamically load objects.

Method Detail

setCheckNullIds

public void setCheckNullIds(boolean check)
Set a flag that causes warning messages to be displayed if an object with no ID is added to the cache.


getElementName

public java.lang.String getElementName()
Return the name of our XML element, required by XmlObject.

Specified by:
getElementName in interface XmlObject
Specified by:
getElementName in class AbstractXmlObject

setSuppressedTypes

public void setSuppressedTypes(Type[] types)
Specifies a list of types that are to be kept out of the cache. We'll still provide an interface for accessing them, but they will never be retained in the cache.

This makes usage of some PersistentObject types like WSUser and WorkflowTask more convenient, since we never want them in the cache, but its nice not to have special case checks in lots of places. Instead we let the cache decide.

This does not affect objects already in the cache, you should call this shortly after cache construction, or clear it yourself.


setNegativeCachedTypes

public void setNegativeCachedTypes(Type[] types)
Sets the list of types for which we perform negative caching - that is, we track object's which don't exist and don't hit the repository to query to see if they exist. NOTE: designating a type as negative cached will mean that a query for a single object will result in a one-time hit to fetch all objects of that type from the repository. For that reason, this should only be set on the Server's cache. (Setting this for the LocalSession cache will only hurt).


clearSuppressedTypes

public void clearSuppressedTypes()
Clear the suppression option for all types, allowing them to be in the cache.

This was added mostly for an old cache test that wanted to load up the cache with WorkflowCases's and other normally suppressed things.


isSuppressedType

public boolean isSuppressedType(Type t)
Test to see if a type is being suppressed.


isDefaultSuppressedType

public static boolean isDefaultSuppressedType(Type t)
Test to see if a type is by default suppressed.


getObject

public PersistentObject getObject(Type type,
                                  java.lang.String name,
                                  java.lang.String id)
                           throws WavesetException
Get an object by name or id, preferring id. Handle one null parameter, has the same semantics as getObject. Three valid cases: name & id != null id == null, name != null id != null, name == null

Throws:
WavesetException

getObject

public PersistentObject getObject(Type type,
                                  java.lang.String id)
                           throws WavesetException
Search for an object in the cache, and dynamically load it if it isn't yet resident.

Throws an exception if the object wasn't found. What the exception is, depends on the ObjectLoader being used. This should be formalized in to a com.waveset.exception object that we can document and use in all ObjectLoader implementations.

If the loader silently returns null, we'll build our own exception, otherwise we'll propagate the loader's exception. In the most common configuration, the loader will encapsulate a Repository and throw ItemNotFound. We can't specify that here though without either introducing a repository package dependency (circular), or moving common exceptions like this to their own package.

!! Sigh, code expects ItemNotFound, but to get that we either have to generate it ourselves, or call the appropriate ObjectLoader method if we want errors thrown. I don't like this..

NOTE: unlike getAllObjects, getObject will NOT traverse subtypes if they exist. This is harder to rationalize here since there could be more than one object with the given name.

Throws:
WavesetException

getObject

public PersistentObject getObject(Type type,
                                  java.lang.String id,
                                  java.util.Map options)
                           throws WavesetException
Object accessor that supports a map of options like LighthouseContext. The only option we recognize is OP_SUBTYPES.

Throws:
WavesetException

getObjectIfExists

public PersistentObject getObjectIfExists(Type type,
                                          java.lang.String id)
                                   throws WavesetException
Search for an object in the cache, and dynamically load it if it isn't yet resident.

Does not throw an exception if the object wasn't found.

Throws:
WavesetException

getObjectIfExists

public PersistentObject getObjectIfExists(Type type,
                                          java.lang.String id,
                                          java.util.Map options)
                                   throws WavesetException
Object accessor that supports a map of options like LighthouseContext. The only option we recognize is OP_SUBTYPES.

Throws:
WavesetException

getObjectWithSubtypes

public PersistentObject getObjectWithSubtypes(Type type,
                                              java.lang.String id)
                                       throws WavesetException
Look for an object whose type may be a subtype of the given type.

Throws:
WavesetException

getObjectWithSubtypesIfExists

public PersistentObject getObjectWithSubtypesIfExists(Type type,
                                                      java.lang.String id)
                                               throws WavesetException
Look for a an object in the cache, for a type that may define subtypes. Used primarily for TaskDefinition.

Throws:
WavesetException

findObject

public PersistentObject findObject(Type type,
                                   java.lang.String id)
                            throws InternalError
Search for an object in the cache, but do not load it if it does not exist.

We do not check cache consistency here either. You get whatever happens to be in he cache at this moment.

Throws:
InternalError

addObjects

public void addObjects(java.util.Collection objects)
                throws WavesetException
Add a collection of objects to the cache. This is equivalent to calling addObject for each member of the collection.

Throws:
WavesetException
See Also:
addObject(com.waveset.object.PersistentObject)

addObject

public void addObject(PersistentObject o)
               throws WavesetException
Add an object to the cache, replacing the current version of the object if one exists. Version tracking is performed by always interning objects wrapped by an ObjectHandle, to update the version we first locate the handle, and change the handle's pointer.

The object must have either an id or a name since we need a key. If it has neither, an internal error is thrown.

We don't check cache consistency here since we're adding objects and are not affected by the current objects.

Throws:
WavesetException

decacheObject

public void decacheObject(Type type,
                          java.lang.String id)
                   throws InternalError
Decache an object. This will remove the resolved PersistentObject if it is found, but it leaves the ObjectHandle in the cache. This is suitable for use when the object still exists, we just want to reload it the next time it is referenced.

If the object no longer exists (its been deleted from the repository) then you should call deleteObject. This will remove all record of the object. We don't have to check cache consistency here, just remove it if it exists.

Throws:
InternalError

handlePossibleRename

public void handlePossibleRename(Type type,
                                 java.lang.String id,
                                 java.lang.String newName)
                          throws WavesetException
Handles the case of an object being possibly renamed. This implicitly decaches the object as well.

Throws:
WavesetException

decacheObject

public void decacheObject(PersistentObject obj)
                   throws InternalError
Remove an object from the cache, but leave the handle.

Throws:
InternalError

deleteObject

public void deleteObject(Type type,
                         java.lang.String id)
                  throws InternalError
Remove an object and its handle from the cache.

This would be called if the object had been deleted and there is no longer a valid object with this name or id.

Throws:
InternalError

deleteObject

public void deleteObject(PersistentObject obj)
                  throws InternalError
Remove an object and its handle from the cache.

Throws:
InternalError

addPath

public void addPath(ObjectGroup org)
             throws WavesetException
Throws:
WavesetException

getHandle

protected com.waveset.object.ObjectHandle getHandle(PersistentObject o)
                                             throws WavesetException
Retreive or create a handle for this object in the cache. This should only be called by the ObjectRef constructor that takes a PersistentObject.

If the object is currently cached, we return the cache handle. If the object is not in a cache, WE DO NOT ADD IT! To get here, the object would have to have been pointing at this cache in order to perform resolution, but it is not "in" the cache.

We don't know where this object came from, it is frequently a temporary object being analyzed for correctness and we don't want it left behind in the cache just because someone manufactured a reference to it.

We can get in to this situation often in the authorization code which likes to build ObjectRef objects as a way to package a type/id/name combination without every storing the reference.

One consequence of this is that a object without an ID can end up being added to the server cache.

Throws:
WavesetException

clear

public void clear()
Remove all objects from the cache.

This obliterates everything, including the handles. Compare with clearObjects which preserves the handles.


clearObjects

public void clearObjects()
Remove all resolved objects, but preserves the handles.


clearObjects

public void clearObjects(Type type)
Remove all resolved objects of a particular type, but preserves the handles.


getObjects

public java.util.ArrayList getObjects(Type type)
                               throws WavesetException
Return a list of objects of a given type.

Throws:
WavesetException

getObjects

public java.util.ArrayList getObjects(Type type,
                                      WSAttributes atts)
                               throws WavesetException
Return a list of objects of a given type, qualified by a collection of attributes.

Throws:
WavesetException

getObjects

public java.util.ArrayList getObjects(Type type,
                                      AttributeCondition[] attrConds)
                               throws WavesetException
Return a list of objects of a given type, qualified by an array of attribute conditions.

Throws:
WavesetException

getObjects

public java.util.ArrayList getObjects(Type type,
                                      java.util.List attrConds)
                               throws WavesetException
Return a list of objects of a given type, qualified by an array of attribute conditions. Conditions are specifies as a list of AttributeCondition objects.

Throws:
WavesetException

getAdmins

public java.util.List getAdmins()
                         throws WavesetException
Helper method that returns a filtered list of WSUsers that have one or more capabilities (are members of one or more AdminGroups) and control one or more Organizations (ObjectGroups), or are assigned one or more AdminRoles.

Throws:
WavesetException

getAllObjects

public java.util.ArrayList getAllObjects(Type type)
                                  throws WavesetException
Return a list of objects of a given type including subtypes.

Throws:
WavesetException

getAllObjects

public java.util.ArrayList getAllObjects(Type type,
                                         WSAttributes atts)
                                  throws WavesetException
Return a list of objects of a given type including subtypes, qualified by a collection of attributes.

Throws:
WavesetException

getAllObjects

public java.util.ArrayList getAllObjects(Type type,
                                         AttributeCondition[] attrConds)
                                  throws WavesetException
Return a list of objects of a given type including subtypes, qualified by an array of attribute conditions.

Throws:
WavesetException

getCachedObjects

public java.util.ArrayList getCachedObjects(Type type)
                                     throws WavesetException
Return a list of objects currently in the cache, that have a certain type.

NOTE: Unlike getObjects, this does not traverse subtypes.

Throws:
WavesetException

getCachedObjects

public java.util.ArrayList getCachedObjects(Type type,
                                            WSAttributes atts)
                                     throws WavesetException
Return a list of objects currently in the cache, that have a certain type and attributes.

NOTE: Unlike getObjects, this does not traverse subtypes.

Throws:
WavesetException

getCachedObjects

public java.util.ArrayList getCachedObjects(Type type,
                                            AttributeCondition[] attrConds)
                                     throws WavesetException
Return a list of objects currently in the cache, that have a certain type and meet certain attribute conditions.

NOTE: Unlike getObjects, this does not traverse subtypes.

Throws:
WavesetException

resolve

public PersistentObject resolve(ObjectRef ref)
                         throws WavesetException
Resolve a single reference through this cache.

Throws:
WavesetException

importObjectFile

public void importObjectFile(java.lang.String filename)
                      throws WavesetException
Import a file of object definitions into the cache.

Throws:
WavesetException

importObjects

public void importObjects(java.lang.String xml)
                   throws WavesetException
Import a file of objects into the cache. This is intended mostly for testing object resolution without requiring a repository, but is also useful for standalone applications that carry simple "repositories" in files.

Throws:
WavesetException

parseXml

public void parseXml(org.w3c.dom.Element e)
              throws WavesetException
Deserialization method used by importObjects, and also now required by XmlObject.

Throws:
WavesetException

toXml

public void toXml(java.lang.StringBuffer b,
                  int indent)
Serialize the entire cache contents, to a string buffer.

Specified by:
toXml in interface XmlObject
Specified by:
toXml in class AbstractXmlObject

exportObjectFile

public void exportObjectFile(java.lang.String filename)
                      throws WavesetException
Serialize the cache to a file.

Throws:
WavesetException

validate

public void validate()
Run some validation rules over the cache. Typically used to track down cache cross link problems.