org.hd.d.pg2k.svrCore
Class ExhibitPropsComputable

java.lang.Object
  extended by org.hd.d.pg2k.svrCore.ExhibitPropsComputable
All Implemented Interfaces:
java.io.ObjectInputValidation, java.io.Serializable, MemoryTools.Compactable, MemoryTools.Internable

public final class ExhibitPropsComputable
extends java.lang.Object
implements java.io.Serializable, java.io.ObjectInputValidation, MemoryTools.Internable, MemoryTools.Compactable

Immutable (and serialisable) store of all immutable computable auxiliary properties of a single exhibit. These are properties that can be computed from the basic exhibit binary data and that generally do not need to be recomputed (unless that exhibit changes, or if we upgrade the code and can get "better" values).

Some of the attributes contained in this object may be expensive to compute (and may require reading the entire exhibit) and thus this object is precomputed on the master server (or offline) where the exhibit is available from fast local storage in its entirety.

This is designed to be efficient on the wire and in memory, since these details will be held for each and every exhibit.

Some data in this object is transient and recomputable from other fields and is recomputed if this object is serialised and deserialised or is kicked out of memory due a shortage.

The equals() and hashCode() of this class can be very expensive, so intern()ing it can be too. However, we do intern() some of its elements.

The construction of this item is brittle, so that if we cannot construct it all, correctly, then we veto construction entirely, so as to avoid results from transient failures persisting indefinitely.

See Also:
Serialized Form

Field Summary
private  int _hash
          Private cache of the hash value; initially zero, and zero for an EMPTY instance.
private static boolean ATTEMPT_C7BS_COMPRESSION
          If true then attempt in-memory compression of matadata to save space with Compact7BitString.
private static boolean ATTEMPT_ROBA_COMPRESSION
          If true then attempt in-memory ZIP compression of metadata to save space.
private static boolean CACHE_DECODED_METADATA
          If true then cache the decoded metadata via a SoftReference.
private static boolean DEFER_COMPACTION
          If true then defer compaction of metadata.
static ExhibitPropsComputable EMPTY
          Shared empty instance.
private static javax.xml.parsers.DocumentBuilderFactory factory
          Create a factory to re-use for each parse; never null.
private static java.lang.String MDPREFIX
          Common "assumed" prefix on XML metadata.
private static int MDPREFIX_LENGTH
           
private static java.lang.String MDSUFFIX
          Common "assumed" suffix on XML metadata.
private static int MDSUFFIX_LENGTH
           
private  java.lang.Object metadata
          Metadata for the exhibit; null if none available.
private  java.lang.ref.SoftReference<org.w3c.dom.Node> metadataDecoded
          Decoded form of metadata; null if not decoded or no metadata.
static Compact7BitString.StaticDictionary sDict
          Shared static dictionary for use with in-memory Compact7BitString metadata.
private static long serialVersionUID
          Our serial version...
private static boolean VAL_MD_SEMANTICS
          If true, test semantics of metadata somewhat during object validation; can be very expensive.
private  java.awt.Dimension xyDimensions
          X,Y dimensions in pixels for images (moving or still) that have a fixed rectangular dimension, else null.
 
Constructor Summary
private ExhibitPropsComputable()
          Make an empty instance.
private ExhibitPropsComputable(java.awt.Dimension xyDim, java.lang.Object metadata)
          Make non-empty instance.
 
Method Summary
private static java.lang.Object _compressTrimmedMetadata(java.lang.String mdTrimmed)
          Attempt to compress supplied already-trimmed metadata; returns null if input is null.
private  int _computeHash()
          Compute the hash value.
static java.lang.String _trimStringFormOfOuterMetadataTag(java.lang.String mdString)
          Remove explicit fixed outer tag to save a little space, or null if input is null.
 void compact()
          Compact the internal representation of this instance (and its sub-objects) if possible.
static ExhibitPropsComputable createExhibitPropsComputable(ExhibitStaticAttr esa, AllExhibitProperties.ExhibitDataSource ds)
          Factory method to create a fully populated ExhibitPropsComputable object.
 boolean equals(java.lang.Object obj)
          Equal if all the members are.
 org.w3c.dom.Node getMetadata()
          Get exhibit metadata; null if none available.
 java.lang.String getMetadataAsXML()
          Get metadata as full XML string surrounded with top-level tags; null if no metadata.
 java.awt.Dimension getXyDimensions()
          Get x,y dimensions in pixels for images (moving or still) that have a fixed rectangular dimension, else null.
 int hashCode()
          Hash based on the dimensions, else on the metadata.
private static org.w3c.dom.Node parseMetadata(java.lang.String xml)
          Parse metadata from XML String format; never null.
protected  java.lang.Object readResolve()
          Deserialise: use constructor for validation, defensive copying, etc.
 java.lang.String toString()
          Human-readable summary.
 void validateObject()
          Validate fields/state.
protected  java.lang.Object writeReplace()
          Serialise: write in the best format for the wire.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

EMPTY

public static final ExhibitPropsComputable EMPTY
Shared empty instance.


MDPREFIX

private static final java.lang.String MDPREFIX
Common "assumed" prefix on XML metadata.

See Also:
Constant Field Values

MDPREFIX_LENGTH

private static final int MDPREFIX_LENGTH

MDSUFFIX

private static final java.lang.String MDSUFFIX
Common "assumed" suffix on XML metadata.

See Also:
Constant Field Values

MDSUFFIX_LENGTH

private static final int MDSUFFIX_LENGTH

xyDimensions

private final java.awt.Dimension xyDimensions
X,Y dimensions in pixels for images (moving or still) that have a fixed rectangular dimension, else null. If this is non-null then x and y are strictly positive.

Because Dimension is mutable, we hand out copies of it to callers.


sDict

public static final Compact7BitString.StaticDictionary sDict
Shared static dictionary for use with in-memory Compact7BitString metadata. We expose this to help generate tuned dictionary values; this is safe to do since this dictionary is immutable.


metadata

private volatile java.lang.Object metadata
Metadata for the exhibit; null if none available. This may exist in a number of formats for efficiency "on the wire" and to save space in memory.

Note that this is stored without the redundant top-level tag.

Marked volatile to allow safe lockless update by compact().


CACHE_DECODED_METADATA

private static final boolean CACHE_DECODED_METADATA
If true then cache the decoded metadata via a SoftReference.

See Also:
Constant Field Values

metadataDecoded

private transient java.lang.ref.SoftReference<org.w3c.dom.Node> metadataDecoded
Decoded form of metadata; null if not decoded or no metadata. Held via a SoftReference to allow this (redundant and bulky) decoded data's memory to be freed.

Transient since this contains no unique data to serialise.

Accessed (and set upon demand) by getMetadata().


factory

private static final javax.xml.parsers.DocumentBuilderFactory factory
Create a factory to re-use for each parse; never null. Hold a lock on this object while using it in case the factory is not thread-safe. It is assumed that multiple document builders created by this factory are safe with respect to one another providing each is single-threaded.


ATTEMPT_ROBA_COMPRESSION

private static final boolean ATTEMPT_ROBA_COMPRESSION
If true then attempt in-memory ZIP compression of metadata to save space.

See Also:
Constant Field Values

ATTEMPT_C7BS_COMPRESSION

private static final boolean ATTEMPT_C7BS_COMPRESSION
If true then attempt in-memory compression of matadata to save space with Compact7BitString.

See Also:
Constant Field Values

serialVersionUID

private static final long serialVersionUID
Our serial version...

See Also:
Constant Field Values

VAL_MD_SEMANTICS

private static final boolean VAL_MD_SEMANTICS
If true, test semantics of metadata somewhat during object validation; can be very expensive.

See Also:
Constant Field Values

_hash

private transient int _hash
Private cache of the hash value; initially zero, and zero for an EMPTY instance. Thread-safe as int access guaranteed atomic.


DEFER_COMPACTION

private static final boolean DEFER_COMPACTION
If true then defer compaction of metadata. If true, then (any) compaction is NOT done during construction or deserialisation, but until some later point such as a call to compact().

This should save a lot of time constructing/deserialising data before the first operations can be performed on it and where memory space is not the primary constraint.

See Also:
Constant Field Values
Constructor Detail

ExhibitPropsComputable

private ExhibitPropsComputable()
Make an empty instance.


ExhibitPropsComputable

private ExhibitPropsComputable(java.awt.Dimension xyDim,
                               java.lang.Object metadata)
Make non-empty instance. This does not intern() any of its arguments (so any that can usefully be intern()ed should already have been).

This may defensively copy mutable argument values.

Parameters:
xyDim - xy (positive) dimensions in pixels or null if none
metadata - normalised metadata else null if none.
Method Detail

getXyDimensions

public java.awt.Dimension getXyDimensions()
Get x,y dimensions in pixels for images (moving or still) that have a fixed rectangular dimension, else null. If this is non-null then x and y are strictly positive.

We return a copy of our internal data.


getMetadataAsXML

public java.lang.String getMetadataAsXML()
Get metadata as full XML string surrounded with top-level tags; null if no metadata.

Returns:
null if no metadata

getMetadata

public org.w3c.dom.Node getMetadata()
Get exhibit metadata; null if none available.


parseMetadata

private static org.w3c.dom.Node parseMetadata(java.lang.String xml)
                                       throws java.io.IOException,
                                              org.xml.sax.SAXException,
                                              javax.xml.parsers.ParserConfigurationException
Parse metadata from XML String format; never null.

Parameters:
xml - well-formed non-null non-empty XML metadata
Returns:
non-null DOM node
Throws:
java.io.IOException
org.xml.sax.SAXException
javax.xml.parsers.ParserConfigurationException

_compressTrimmedMetadata

private static java.lang.Object _compressTrimmedMetadata(java.lang.String mdTrimmed)
Attempt to compress supplied already-trimmed metadata; returns null if input is null. Given the metadata in full XML form, returns it trimmed, and compressed if possible.


createExhibitPropsComputable

public static ExhibitPropsComputable createExhibitPropsComputable(ExhibitStaticAttr esa,
                                                                  AllExhibitProperties.ExhibitDataSource ds)
                                                           throws java.io.IOException
Factory method to create a fully populated ExhibitPropsComputable object. This is given the a data source from which it can fetch the exhibit data one or more times to do its computations.

The data source object is not stored in the object.

This will veto any attempt at construction if the data object is not fully loaded, ie all available immediately with high bandwidth.

Underlying methods, such as getMetadata(), can throw all sorts of horrors, such as an Error, so we try very hard to fail gracefully if this happens and only throw an IOException.

Throws:
java.io.IOException

_trimStringFormOfOuterMetadataTag

public static java.lang.String _trimStringFormOfOuterMetadataTag(java.lang.String mdString)
Remove explicit fixed outer tag to save a little space, or null if input is null. Not for casual use, and not part of the supported API of this class.


readResolve

protected java.lang.Object readResolve()
Deserialise: use constructor for validation, defensive copying, etc. Also resolve all empty instances to a singleton as a minor optimisation, and immediately intern() new values so as to immediately discard duplicates (eg of exhibits already known) ASAP to minimise heap churn.


writeReplace

protected java.lang.Object writeReplace()
Serialise: write in the best format for the wire. To get best aggregate compressed size on the wire, eg where the compressed stream contains many similar non-identical instances, we always write out the metadata in its String format (minus the outer tags) regardless of how it is actually held in memory. This also makes us immune to changes in the the internals of the other formats and allows use of a static dictionary with Compact7BitString for better in-memory compression (ie effectively cross-instance compression).

This allows a stream compressor to effectively compress the redundancy between instances of this class on the wire as well as internal redundancies.

We assume that there will almost never be identical instances on one stream so we don't mind writing new copies each time where it does happen.


validateObject

public void validateObject()
                    throws java.io.InvalidObjectException
Validate fields/state. Called in the constructor and possibly after de-serialising.

Barf if something bad is found. (Maybe allow some extra info in debug version.)

Specified by:
validateObject in interface java.io.ObjectInputValidation
Throws:
java.io.InvalidObjectException

equals

public boolean equals(java.lang.Object obj)
Equal if all the members are.

Overrides:
equals in class java.lang.Object

toString

public java.lang.String toString()
Human-readable summary.

Overrides:
toString in class java.lang.Object

_computeHash

private int _computeHash()
Compute the hash value. As well as being used for hash tables, this will be used to detect changes in the representation of computed data, ie for the overall AEP hash, so this should include all significant elements.

Note that this also means that the AEP hash contains a semantically-significant sampling of the exhibit data as well as such things as length and timestamp from the AEID.


hashCode

public int hashCode()
Hash based on the dimensions, else on the metadata.

Overrides:
hashCode in class java.lang.Object

compact

public void compact()
Compact the internal representation of this instance (and its sub-objects) if possible. This has no effect on the logical content of this instance in-memory or serialised, is guaranteed to be safe to run concurrently with other uses of this instance (and will take any locks as needed to work incrementally), and may do nothing but consume some CPU cycles.

This may be able to convert some state to a more memory-efficient representation after construction or deserialisation, and is suitable to be called by a background thread.

We don't prevent multiple concurrent calls to this routine, since they are at worst wasteful of CPU but not unsafe.

Specified by:
compact in interface MemoryTools.Compactable

DHD Multimedia Gallery V1.50.55

Copyright (c) 1996-2008, Damon Hart-Davis. All rights reserved.