org.hd.d.pg2k.svrCore.props
Class PropertiesDiff

java.lang.Object
  extended by org.hd.d.pg2k.svrCore.props.PropertiesDiff
All Implemented Interfaces:
java.io.ObjectInputValidation, java.io.Serializable

public class PropertiesDiff
extends java.lang.Object
implements java.io.Serializable, java.io.ObjectInputValidation

An immutable diff/patch representation for well-behaved simple String-->String Properties. These diffs can be used to send just changes/deltas over the wire for well-behaved pure-String Properties.

Where all property names (ie keys) are pure 8-bit values a more compact internal (still immutable) form will be used for them.

Also individual values will be held in a more compact form where possible.

This class itself is immutable and Serializable, and designed to be efficient on the wire.

Note that comments are not retained, and the diff elements are ordered to allow efficient compression.

The diff notes elements that are removed and that are changed/added with the new/changed value in its entirety.

This does not record changes below the level of a single element, ie may not be effective for small number of large, often-changing values.

This class does not attempt to intern() keys or values unless asked to.

Author:
DHD
See Also:
Serialized Form

Field Summary
private  int _hash
          Cached hash value; initially zero.
private  java.util.NavigableSet<java.lang.CharSequence> deletedNames
          The logically immutable in-order set of items/names entirely removed; never null.
static PropertiesDiff EMPTY_DIFF
          Immutable empty diff.
private static java.util.Properties EMPTY_PROPERTIES
          Private empty Properties map; never changed, never null.
private  java.util.NavigableMap<java.lang.CharSequence,java.lang.CharSequence> newValues
          The logically immutable in-order map from items/names to the new/changed values; never null.
private static long serialVersionUID
          Serial UID.
 int sizeAfter
          The entry count for the output properties set as a sanity-check; guaranteed non-negative.
 int sizeBefore
          The entry count for the input properties set as a sanity-check; guaranteed non-negative.
static java.util.Comparator<java.lang.CharSequence> SORT_ORDER
          Comparator that provides total ordering for sorted results; not null.
 
Constructor Summary
PropertiesDiff()
          Make new empty diff instance.
PropertiesDiff(int sizeBefore, int sizeAfter, java.util.Set<? extends java.lang.CharSequence> deleted, java.util.Map<? extends java.lang.CharSequence,? extends java.lang.CharSequence> added)
          Create diff instance.
 
Method Summary
private static java.util.Set<Tuple.Pair<java.lang.CharSequence,java.lang.CharSequence>> _computeChangeValues(java.util.Properties p)
          Create "change" values from a Properties instance; never null.
static java.util.Properties applyDiff(java.util.Properties p1, PropertiesDiff diff)
          Applies diff to an extant Properties instance to generate a new AEP instance; never null.
private static java.util.NavigableSet<java.lang.CharSequence> convertAllToNameOrAllToString(java.util.Set<? extends java.lang.CharSequence> in)
          Convert all supplied CharSequence values to Name else convert them all to String; never null.
static PropertiesDiff createAsStandAloneDiff(java.util.Properties p1)
          Create diff against empty Properties.
static PropertiesDiff createDiff(java.util.Properties p1, java.util.Properties p2, boolean force, boolean intern)
          Create diff between two Properties instances; never null.
static java.util.Properties createFromStandAloneDiff(PropertiesDiff pd)
          Create from diff against empty Properties.
 boolean equals(java.lang.Object obj)
          Equal iff all fields are identical.
 java.util.SortedMap<java.lang.CharSequence,java.lang.CharSequence> getNewValues()
          Get (immutable) newValues; never null.
 int hashCode()
          Hash code depends on all deleted/changed elements; guaranteed zero for an empty diff, non-zero otherwise.
 boolean isEmpty()
          Returns true iff the diff is "empty", ie no deletions nor additions/changes.
static Tuple.Pair<java.util.Properties,java.lang.Long> loadFromFile(java.io.File filename)
          Load properties with timestamp; never null.
private  void readObject(java.io.ObjectInputStream ois)
          Deserialise.
protected  java.lang.Object readResolve()
          Deserialise: including discarding duplicate empty values.
 java.lang.String toString()
          Human-readable summary of state.
 void validateObject()
          Checks that the object is internally consistent.
private  void writeObject(java.io.ObjectOutputStream oos)
          Write out a less-redundant form of our internal information.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

SORT_ORDER

public static final java.util.Comparator<java.lang.CharSequence> SORT_ORDER
Comparator that provides total ordering for sorted results; not null.


deletedNames

private transient java.util.NavigableSet<java.lang.CharSequence> deletedNames
The logically immutable in-order set of items/names entirely removed; never null. This field is NOT serialised directly.

Keys in this set are always of a single type, eg all String or all Name.


newValues

private transient java.util.NavigableMap<java.lang.CharSequence,java.lang.CharSequence> newValues
The logically immutable in-order map from items/names to the new/changed values; never null. This field is NOT serialised directly.

Keys in this map are always of a single type, eg all String or all Name.

Values in this map may be of mixed type.


sizeBefore

public final int sizeBefore
The entry count for the input properties set as a sanity-check; guaranteed non-negative.


sizeAfter

public final int sizeAfter
The entry count for the output properties set as a sanity-check; guaranteed non-negative.


EMPTY_DIFF

public static final PropertiesDiff EMPTY_DIFF
Immutable empty diff.


EMPTY_PROPERTIES

private static final java.util.Properties EMPTY_PROPERTIES
Private empty Properties map; never changed, never null.


_hash

private transient int _hash
Cached hash value; initially zero. We cache this because (re)computing it requires looking at every char in every key and value, ie potentially horribly expensive.

Since access is atomic, this need not be marked volatile.

Never set to zero once non-zero.


serialVersionUID

private static final long serialVersionUID
Serial UID.

See Also:
Constant Field Values
Constructor Detail

PropertiesDiff

public PropertiesDiff()
Make new empty diff instance.


PropertiesDiff

public PropertiesDiff(int sizeBefore,
                      int sizeAfter,
                      java.util.Set<? extends java.lang.CharSequence> deleted,
                      java.util.Map<? extends java.lang.CharSequence,? extends java.lang.CharSequence> added)
Create diff instance. We defensively copy the potentially-mutable Collection argument, and perform optimisation on internal representation.

Parameters:
sizeBefore - size of input Properties; non-negative
sizeAfter - size of output Properties; non-negative
deleted - names present in input and not present in output; non-null
added - new/changed name-value pairs in output; non-null
Method Detail

convertAllToNameOrAllToString

private static final java.util.NavigableSet<java.lang.CharSequence> convertAllToNameOrAllToString(java.util.Set<? extends java.lang.CharSequence> in)
Convert all supplied CharSequence values to Name else convert them all to String; never null. Values already of the correct type are not converted, and all String values will be intern()ed.


getNewValues

public java.util.SortedMap<java.lang.CharSequence,java.lang.CharSequence> getNewValues()
Get (immutable) newValues; never null. Keys are always of a single (immutable) type such as String for each instance, that should work in hash or sorted collections.

Values may be of a mix of (immutable) types within one result.

The comparator is SORT_ORDER and we use a SortedMap so as not to rely on hashCode() and equals(), eg we can look up with a String key in a table whose actual keys are Name.


_computeChangeValues

private static java.util.Set<Tuple.Pair<java.lang.CharSequence,java.lang.CharSequence>> _computeChangeValues(java.util.Properties p)
Create "change" values from a Properties instance; never null. This is the set of values to be added to an empty Properties value to regenerate this one.

The first element in each Pair is the (non-null) property name; the second element is the (non-null) property value.

Parameters:
p - non-null pure String-->String properties set

createAsStandAloneDiff

public static PropertiesDiff createAsStandAloneDiff(java.util.Properties p1)
Create diff against empty Properties. This is a safe, efficient, immutable, Serializable representation for a single Properties instance, where a raw Properties instance may not be safe/robust enough.

Forces intern()ing of the keys and values.


createFromStandAloneDiff

public static java.util.Properties createFromStandAloneDiff(PropertiesDiff pd)
                                                     throws AllExhibitPropertiesDelta.DiffException
Create from diff against empty Properties. Recovers Properties instance created by createAsDiff.

Throws:
AllExhibitPropertiesDelta.DiffException

createDiff

public static PropertiesDiff createDiff(java.util.Properties p1,
                                        java.util.Properties p2,
                                        boolean force,
                                        boolean intern)
                                 throws AllExhibitPropertiesDelta.DiffException
Create diff between two Properties instances; never null. This creates a diff to be applied to an instance of the first argument to recreate the second argument.

This will refuse to create a diff if it seems that the diff is unlikely to be useful, for example:

Parameters:
force - if true then force a diff to be produced even if this routine would normally refuse to do so on efficiency grounds
intern - if true than force intern()ing of all String values
Throws:
AllExhibitPropertiesDelta.DiffException - if no diff can be generated or is unlikely to be worthwhile to use (eg would be more than a fraction of the size of the second AEP)

applyDiff

public static java.util.Properties applyDiff(java.util.Properties p1,
                                             PropertiesDiff diff)
                                      throws AllExhibitPropertiesDelta.DiffException
Applies diff to an extant Properties instance to generate a new AEP instance; never null. The diff must only be applied to the same Properties instance value that the diff was generated from (ie an equal one).

We do very basic/quick sanity checks on the before/after sizes to catch misapplication of a diff to a clearly-inappropriate Properties set.

Throws:
AllExhibitPropertiesDelta.DiffException - if the diff cannot be applied

isEmpty

public boolean isEmpty()
Returns true iff the diff is "empty", ie no deletions nor additions/changes.


equals

public boolean equals(java.lang.Object obj)
Equal iff all fields are identical.

Overrides:
equals in class java.lang.Object

hashCode

public int hashCode()
Hash code depends on all deleted/changed elements; guaranteed zero for an empty diff, non-zero otherwise.

Overrides:
hashCode in class java.lang.Object

toString

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

Overrides:
toString in class java.lang.Object

writeObject

private void writeObject(java.io.ObjectOutputStream oos)
                  throws java.io.IOException
Write out a less-redundant form of our internal information. In particular, since deltas will not usually involve deletion of any values, we make the no-deletions case take no space at all in the serialised form.

None of the values written are intern()ed during serialisation, at the risk of not unifying them with identical values in the object stream, to avoid inadvertently creating permanent intern() overhead for them.

Throws:
java.io.IOException

readObject

private void readObject(java.io.ObjectInputStream ois)
                 throws java.io.IOException,
                        java.lang.ClassNotFoundException
Deserialise. This doesn't work very hard to intern() or optimise or validate state, since readResolve() will pass all the data to a constructor to deal with.

Throws:
java.io.IOException
java.lang.ClassNotFoundException

readResolve

protected java.lang.Object readResolve()
                                throws java.io.ObjectStreamException
Deserialise: including discarding duplicate empty values.

Throws:
java.io.ObjectStreamException

validateObject

public void validateObject()
                    throws java.io.InvalidObjectException
Checks that the object is internally consistent.

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

loadFromFile

public static Tuple.Pair<java.util.Properties,java.lang.Long> loadFromFile(java.io.File filename)
                                                                    throws java.io.IOException
Load properties with timestamp; never null. Requires "end=OK" (trailing) token to indicate undamaged file.

Throws:
java.io.IOException - in case of difficulty loading the file
java.io.FileNotFoundException - if the file is absent/unreadable

DHD Multimedia Gallery V1.60.69

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