package student.web.internal;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.collections.BidiMap;
/**
* This snapshot class stores all of the context information about an object
* that has been retrieved from the persistence store. When an object is
* unmarshled, the information retrieved is stored in this class. Then when the
* object is later marshaled, this information is used to compute which fields
* within the original object have been changed. All changed fields are then
* loaded into the newest object retrieved from the store and persisted. This
* snapshot also allows the developer to store context relating to collections,
* maps, and arrays. The context for these are different then normal field sets.
* For these objects, we must remember the old ordering of objects so we can
* merge changes from the persistence store.
*
* @author mjw87
*
*/
public class Snapshot
{
// This snapshot records all of the information about he object currently in
// use by the application
private static Snapshot local = null;
// This snapshot records all of the information about the newest version of
// the object that has been retrieved from the store.
private static Snapshot newest = null;
/**
* Clear the snapshot of the current local version of the object.
*/
public static void clearLocal()
{
local = null;
}
/**
* Clear the statically stored Newest snapshot.
*/
public static void clearNewest()
{
newest = null;
}
/**
* Get the snapshot for the object in use in the application.
*
* @return The snapshot.
*/
public static Snapshot getLocal()
{
return local;
}
/**
* Get the newest snapshot found for the current object being persisted
* or retrieved.
*
* @return The newest snapshot.
*/
public static Snapshot getNewest()
{
return newest;
}
/**
* This looks up the id for the source object using local context from
* when the object was retrieved or a snapshot tagged as the new version
* of an object.
*
* @param source The object to find the id for.
* @param generate Indicates whether to generate a new id for the object.
* @return The ID.
*/
public static UUID lookupId( Object source, boolean generate )
{
UUID id = local.findId( source );
if ( id != null )
{
return id;
}
if ( newest != null )
id = newest.findId( source );
if ( generate )
{
id = UUID.randomUUID();
}
return id;
}
/**
* Set the local snapshot that contains all of the information about the
* object currently in use by the application.
*
* @param snapshot The snapshot to remember as the local snapshot.
*/
public static void setLocal( Snapshot snapshot )
{
local = snapshot;
}
/**
* Set the newest snapshot found for the current object being analyzed by
* the persistence store.
*
* @param snapshot The snapshot to remember as the newest snapshot.
*/
public static void setNewest( Snapshot snapshot )
{
newest = snapshot;
}
Map<Object, Map<String, Object>> objToFieldSet =
new IdentityHashMap<Object, Map<String, Object>>();
Map<Object, Collection<Object>> objToOrigObj =
new IdentityHashMap<Object, Collection<Object>>();
// <Object,UUID>
BidiMap objToUuid = new DualBidiIdentityHashMap<Object, UUID>();
/**
* Using a provided object, find the UUID that identifies it or null if
* there is none.
*
* @param source
* the object to lookup a UUID for
* @return the UUID that identifies this object in the persistence store.
*/
public UUID findId( Object source )
{
return (UUID)objToUuid.get( source );
}
/**
* Find the object that is identified by a UUID. This is limited to the
* scope of the Snapshot.
*
* @param collectionId
* The UUID to lookup an object for
* @return The object corresponding to this id
*/
public Object findObject( UUID collectionId )
{
return this.objToUuid.getKey( collectionId );
}
/**
* Get the Base object associated with a specified UUID. This will only be
* non null if the UUID identifies a collection, map, or array. Otherwise,
* there is no base object. This method is provided to obtain original
* collections to identify a different ordering in a list.
*
* @param sourceId
* The UUID to lookup
* @return the list with the original ordering as seen when the object was
* originally retrieved from the store.
*/
public Object getBaseObject( UUID sourceId )
{
Object orig = this.objToUuid.getKey( sourceId );
if ( orig == null )
return null;
return objToOrigObj.get( orig );
}
/**
* Using an Id, lookup the corresponding fieldset as seen when the object
* was retrieved from the store.
*
* @param id
* the identifier for the object.
* @return the field set corresponding to the id.
*/
public Map<String, Object> getFieldSetFromId( UUID id )
{
if ( id == null )
return null;
Object source = objToUuid.getKey( id );
return objToFieldSet.get( source );
}
/**
* Using an object reference, lookup the corresponding fieldset from the
* store.
*
* @param source The object to look up.
* @return The fieldset for the source object.
*/
public Map<String, Object> getFieldSetFromObject( Object source )
{
return objToFieldSet.get( source );
}
/**
* Resolve a Collection or array to this snapshot. This will track the
* object for eventual persistence back to the store.
*
* @param id
* the UUID to associate with this object
* @param result
* the object that has been retrieved from the store.
* @param baseCollection
* The collection ordering as it was seen when the object was
* retrieved.
*/
public void resolveObject(
UUID id,
Object result,
Collection<Object> baseCollection )
{
resolveObject0( id, result, null );
objToOrigObj.put( result, baseCollection );
}
/**
* Resolve a non collection or array object in this snapshot.
*
* @param id
* the UUID to associate with this object
* @param result
* the result of retrieving the object from the store.
* @param fields
* The fieldset that was present when the object was last
* retrieved.
*/
public void resolveObject(
UUID id,
Object result,
Map<String, Object> fields )
{
resolveObject0( id, result, fields );
}
private void resolveObject0(
UUID id,
Object result,
Map<String, Object> fields )
{
objToUuid.put( result, id );
objToFieldSet.put( result, fields );
}
}