package com.ericfeminella.collections
{
import flash.net.ObjectEncoding;
import flash.net.SharedObject;
import flash.utils.Dictionary;
/**
*
* Provides an <code>IMap</code> implementation into the <code>data</code>
* object of a <code>SharedObject</code> on a clients local file system.
*
* <p>
* <code>LocalPersistenceMap</code> allows the <code>data</code> object
* of a <code>SharedObject</code> to be accessed via an <code>IMap</code>
* implementation in order to provide a consistant API for working with
* the underlying data of the <code>SharedObject</code>.
* </p>
*
* @example The following example demonstrates how a client implementation
* of <code>LocalPersistenceMap</code> can be utilized to provide a typical
* <code>IMap</code> implementation into a <code>SharedObject</code>.
*
* <listing version="3.0">
*
* var map:IMap = new LocalPersistenceMap("test", "/");
* map.put("username", "efeminella");
* map.put("password", "43kj5k4nr43r934hcr34hr8h3");
* map.put("admin", true);
*
* </listing>
*
* @see com.ericfeminella.collections.IMap
* @see http://livedocs.adobe.com/flex/3/langref/flash/net/SharedObject.html
*
*/
public class LocalPersistenceMap implements IMap
{
/**
*
* Defines the underlying <code>SharedObject</code> instance in which
* the persistant <code>data</code> is stored.
*
*/
protected var sharedObject:SharedObject = null;
/**
*
* Defines a local reference to the <code>data</code> property of the
* underlying <code>SharedObject</code> instance.
*
* @see http://livedocs.adobe.com/flex/3/langref/flash/net/SharedObject.html#data
*
*/
protected var data:Object = null;
/**
*
* Defines the minimum disc space which is required by the persistant
* <code>SharedObject</code>.
*
*/
protected var minimumStorage:Number = NaN;
/**
*
* <ocde>LocalPersistenceMap</code> constructor creates a reference to
* the persisted <code>SharedObject</code> available from the clients
* local disk. If the <code>SharedObject</code> does not currently exist,
* Flash Player will attempt to created it.
*
* <p>
* If the identifier parameter contains any invalid charachters, they will
* be substituted with underscores
* </p>
*
* @param name of the local <code>SharedObject</code>
* @param the local path to the <code>SharedObject</code>
* @param specifies if the shared object is from a secure domain
* @param minimum amount of disc space required by the shared object
*
* @return true if the write operation was successful, false if not
*
*/
public function LocalPersistenceMap(identifier:String, localPath:String = null, secure:Boolean = false, minimumStorage:int = 500)
{
var pattern:RegExp = /[~%&\;:\"\'<>\?#]/g;
identifier = identifier.replace( pattern, "_" );
sharedObject = SharedObject.getLocal( identifier, localPath, secure );
sharedObject.objectEncoding = ObjectEncoding.AMF3;
sharedObject.flush( minimumStorage );
this.data = sharedObject.data;
this.minimumStorage = minimumStorage;
}
/**
*
* Adds a key and value to the <code>data</code> object of the
* underlying the <code>SharedObject</code> instance.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "user", userVO );
*
* </listing>
*
* @param the key to add to the map
* @param the value of the specified key
*
*/
public function put(key:*, value:*) : void
{
sharedObject.data[key] = value;
sharedObject.flush( minimumStorage );
}
/**
*
* Places all name / value pairs into the current
* <code>IMap</code> instance.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var table:Object = {a: "foo", b: "bar"};
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.putAll( table );
*
* trace( map.getKeys() ); // a, b
* trace( map.getValues() ); // foo, bar
*
* </listing>
*
* @param an <code>Object</code> of name / value pairs
*
*/
public function putAll(table:Dictionary) : void
{
for (var prop:String in table)
{
put( prop, table[prop] );
}
}
/**
*
* <code>putEntry</code> is intended as a pseudo-overloaded
* <code>put</code> implementation whereby clients may call
* <code>putEntry</code> to pass an <code>IHashMapEntry</code>
* implementation.
*
* @param concrete <code>IHashMapEntry</code> implementation
*
*/
public function putEntry(entry:IHashMapEntry) : void
{
put( entry.key, entry.value );
}
/**
*
* Removes a key and value from the <code>data</code> object of the
* underlying the <code>SharedObject</code> instance.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.remove( "admin" );
*
* </listing>
*
* @param the key to remove from the map
*
*/
public function remove(key:*) : void
{
delete sharedObject.data[key];
sharedObject.flush( minimumStorage );
}
/**
*
* Determines if a key exists in the <code>data</code> object of the
* underlying the <code>SharedObject</code> instance.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
*
* trace( map.containsKey( "admin" ) ); //true
*
* </listing>
*
* @param the key in which to determine existance in the map
* @return true if the key exisits, false if not
*
*/
public function containsKey(key:*) : Boolean
{
return sharedObject.data.hasOwnProperty( key );
}
/**
*
* Determines if a value exists in the HashMap instance
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
*
* trace( map.containsValue( adminVO ) ); //true
*
* </listing>
*
* @param the value in which to determine existance in the map
* @return true if the value exisits, false if not
*
*/
public function containsValue(value:*) : Boolean
{
var result:Boolean = false;
for ( var prop:String in data )
{
if ( data[prop] == value )
{
result = true;
break;
}
}
return result;
}
/**
*
* Returns a key value from the HashMap instance
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
*
* trace( map.getKey( adminVO ) ); //admin
*
* </listing>
*
* @param the key in which to retrieve the value of
* @return the value of the specified key
*
*/
public function getKey(value:*) : *
{
var key:String = "";
for ( var prop:String in data )
{
if ( data[prop] == value )
{
key = prop;
break;
}
}
return key;
}
/**
*
* Returns each key added to the <code>data</code> object of the
* underlying the <code>SharedObject</code> instance.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
*
* trace( map.getKeys() ); //admin, editor
*
* </listing>
*
* @return Array of key identifiers
*
*/
public function getValue(key:*) : *
{
var value:*;
for ( var prop:String in data )
{
if ( prop == key )
{
value = data[prop];
break;
}
}
return value;
}
/**
*
* Returns each key added to the <code>data</code> object of the
* underlying the <code>SharedObject</code> instance.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
*
* trace( map.getKeys() ); //admin, editor
*
* </listing>
*
* @return Array of key identifiers
*
*/
public function getKeys() : Array
{
var keys:Array = new Array();
for ( var prop:String in data )
{
keys.push( prop );
}
return keys;
}
/**
*
* Retrieves each value assigned to the <code>data</code> object of
* the underlying the <code>SharedObject</code> instance.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
*
* trace( map.getValues() ); //[object, adminVO],[object, editorVO]
*
* </listing>
*
* @return Array of values assigned for all keys in the map
*
*/
public function getValues() : Array
{
var values:Array = new Array();
for ( var prop:String in data )
{
values.push( data[prop] );
}
return values;
}
/**
*
* Determines the size of the <code>data</code> object of the
* underlying the <code>SharedObject</code> instance.e
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
*
* trace( map.size() ); //2
*
* </listing>
*
* @return the current size of the map instance
*
*/
public function size() : int
{
var length:int = 0;
for ( var key:* in data )
{
length++;
}
return length;
}
/**
*
* Determines if the current <code>data</code> object of the
* underlying the <code>SharedObject</code> instance is empty.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* trace( map.isEmpty() ); //true
*
* map.put( "admin", adminVO );
* trace( map.isEmpty() ); //false
*
* </listing>
*
* @return true if the current map is empty, false if not
*
*/
public function isEmpty() : Boolean
{
return size() <= 0;
}
/**
*
* Resets all key / value assignment in the <code>data</code> object
* of the underlying the <code>SharedObject</code> instance is empty
* to null.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
* map.reset();
*
* trace( map.getValues() ); //null, null
*
* </listing>
*
*/
public function reset() : void
{
for ( var prop:String in data )
{
data[prop] = undefined;
}
sharedObject.flush( minimumStorage );
}
/**
*
* Resets all key / values defined in the <code>data</code> object of
* the underlying the <code>SharedObject</code> instance is empty to
* null with the exception of the specified key.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
*
* trace( map.getValues() ); //[object, adminVO],[object, editorVO]
*
* map.resetAllExcept( "editor", editorVO );
* trace( map.getValues() ); //null, [object, editorVO]
*
* </listing>
*
* @param the key which is not to be cleared from the map
*
*/
public function resetAllExcept(key:*) : void
{
for ( var prop:String in data )
{
if ( prop != key )
{
data[prop] = undefined;
}
}
sharedObject.flush( minimumStorage );
}
/**
*
* Resets all key / values in the <code>data</code> object of the
* underlying the <code>SharedObject</code> instance to null.
*
* @example
*
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
*
* trace( map.size() ); //2
*
* map.clear();
*
* trace( map.size() ); //0
*
* </listing>
*
*/
public function clear() : void
{
for ( var key:* in data )
{
remove( key );
}
sharedObject.flush( minimumStorage );
}
/**
*
* Clears all key / values defined in the <code>data</code> object
* of the underlying the <code>SharedObject</code> instance with the
* exception of the specified key.
*
* @example
*
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:IMap = new LocalPersistenceMap("sharedObjectName");
* map.put( "admin", adminVO );
* map.put( "editor", editorVO );
* trace( map.size() ); //2
*
* map.clearAllExcept( "editor", editorVO );
* trace( map.getValues() ); //[object, editorVO]
* trace( map.size() ); //1
*
* </listing>
*
* @param the key which is not to be cleared from the map
*
*/
public function clearAllExcept(key:*) : void
{
for ( var prop:String in data )
{
if ( prop != key )
{
delete data[prop];
}
}
sharedObject.flush( minimumStorage );
}
/**
*
* Returns an <code>IList</code> of <code>IHashMapEntry</code>
* objects based on the underlying internal map.
*
* @param <code>IList</code> of <code>IHashMapEntry</code> objects
*
*/
public function getEntries() : Array
{
var list:Array = new Array();
for ( var key:String in data )
{
list.push( new HashMapEntry( key, data[key] ) );
}
return list
}
/**
*
* Retrieves the underlying <code>SharedObject</code> instance
* used by the <code>LocalPersistenceMap</code>.
*
* @example
* <listing version="3.0">
*
* import com.ericfeminella.collections.LocalPersistenceMap;
* import com.ericfeminella.collections.IMap;
*
* var map:LocalPersistenceMap = new LocalPersistenceMap("sharedObjectName");
* trace( map.sharedObjectInstance );
*
* </listing>
*
* @return underlying <code>SharedObject</code> instance
*
*/
public function get sharedObjectInstance() : SharedObject
{
return sharedObject;
}
}
}