Skip to content

Commit

Permalink
Refactor to use request objects
Browse files Browse the repository at this point in the history
Added concept of a store request which encapsulates the retrieval of
data from a data source. This will allow application to know when a
query failed or succeeded.
  • Loading branch information
danschultz committed Sep 1, 2011
1 parent dcce70a commit 3a8579e
Show file tree
Hide file tree
Showing 21 changed files with 396 additions and 552 deletions.
41 changes: 4 additions & 37 deletions src/mesh/model/Entity.as
Expand Up @@ -4,7 +4,6 @@ package mesh.model
import com.brokenfunction.json.encodeJson;

import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.flash_proxy;

Expand All @@ -15,9 +14,6 @@ package mesh.model
import mesh.model.associations.Association;
import mesh.model.associations.HasManyAssociation;
import mesh.model.associations.HasOneAssociation;
import mesh.model.load.LoadEvent;
import mesh.model.load.LoadFailedEvent;
import mesh.model.load.LoadSuccessEvent;
import mesh.model.serialization.Serializer;
import mesh.model.source.SourceFault;
import mesh.model.store.Store;
Expand All @@ -29,21 +25,6 @@ package mesh.model

use namespace flash_proxy;

/**
* Dispatched when the result list starts loading its content.
*/
[Event(name="loading", type="mesh.model.load.LoadEvent")]

/**
* Dispatched when the result list has successfully loaded its content.
*/
[Event(name="success", type="mesh.model.load.LoadSuccessEvent")]

/**
* Dispatched when the result list has failed to load its content.
*/
[Event(name="failed", type="mesh.model.load.LoadFailedEvent")]

/**
* An entity.
*
Expand All @@ -67,7 +48,10 @@ package mesh.model
_aggregates = new Aggregates(this);

_status = new EntityStatus(this);
_status.addEventListener(StateEvent.ENTER, handleStatusChange);
_status.addEventListener(StateEvent.ENTER, function(event:StateEvent):void
{
dispatchEvent(event.clone());
});

copy(values, this);
addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, handlePropertyChange);
Expand Down Expand Up @@ -176,23 +160,6 @@ package mesh.model
propertyChanged(event.property.toString(), event.oldValue, event.newValue);
}

private function handleStatusChange(event:StateEvent):void
{
dispatchEvent(event.clone());

if (status.isErrored) {
dispatchEvent( new LoadFailedEvent(LoadFailedEvent.FAILED, _fault) );
}

if (status.isSynced) {
dispatchEvent( new LoadSuccessEvent(LoadSuccessEvent.SUCCESS) );
}

if (status.isBusy) {
dispatchEvent( new LoadEvent(LoadEvent.LOADING) );
}
}

/**
* Returns a generated hash value for this entity. Two entities that represent
* the same data should return the same hash code.
Expand Down
119 changes: 20 additions & 99 deletions src/mesh/model/associations/Association.as
Expand Up @@ -4,34 +4,14 @@ package mesh.model.associations

import flash.errors.IllegalOperationError;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;

import mesh.core.inflection.humanize;
import mesh.core.reflection.Type;
import mesh.model.Entity;
import mesh.model.load.LoadEvent;
import mesh.model.load.LoadFailedEvent;
import mesh.model.load.LoadHelper;
import mesh.model.load.LoadSuccessEvent;
import mesh.model.source.SourceFault;
import mesh.model.store.AsyncRequest;

import mx.events.PropertyChangeEvent;

/**
* Dispatched when the result list starts loading its content.
*/
[Event(name="loading", type="mesh.model.load.LoadEvent")]

/**
* Dispatched when the result list has successfully loaded its content.
*/
[Event(name="success", type="mesh.model.load.LoadSuccessEvent")]

/**
* Dispatched when the result list has failed to load its content.
*/
[Event(name="failed", type="mesh.model.load.LoadFailedEvent")]

/**
* An association class is a proxy object that contains the references to the objects in
* a relationship, where the <em>owner</em> represents the object hosting the association,
Expand All @@ -41,8 +21,6 @@ package mesh.model.associations
*/
public class Association extends EventDispatcher
{
private var _helper:LoadHelper;

/**
* Constructor.
*
Expand All @@ -58,16 +36,9 @@ package mesh.model.associations
_property = property;
_options = options != null ? options : {};

_helper = new LoadHelper(this);

// Watch for assignments to the mapped property on the owner. If the property is reassigned,
// then we'll need the association to wrap the new object.
owner.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, handleOwnerPropertyChange);

addEventListener(LoadEvent.LOADING, function(event:LoadEvent):void
{
executeLoad();
});
}

/**
Expand All @@ -83,22 +54,6 @@ package mesh.model.associations
populateInverseRelationship(entity);
}

private function cleanupLoad():void
{
_loadable = null;
}

/**
* Called by sub-classes if the association's data failed to load.
*
* @param fault The reason for the failure.
*/
protected function failed(fault:SourceFault):void
{
_helper.failed(fault);
cleanupLoad();
}

private function handleOwnerPropertyChange(event:PropertyChangeEvent):void
{
if (event.property is String && event.property.toString() == property) {
Expand All @@ -111,61 +66,34 @@ package mesh.model.associations
*/
public function initialize():void
{
var data:Object = owner[property];
if (!isLazy) {
loaded(data);
} else {
object = data;
}
object = owner[property];
}

/**
* Loads the data for this association. If this is a non-lazy association, then nothing happens.
*/
public function load():void
public function load():AsyncRequest
{
_helper.load();
var request:AsyncRequest = createLoadRequest();
request.responder({result:loaded});
return request;
}

/**
* Called when the association's data needs to be loaded. Sub-classes must override this
* method in order to load the association's data.
*/
protected function executeLoad():void
{

}

private var _loadable:IEventDispatcher;
/**
* Called when the association needs to load its data. Sub-classes must override this method in
* order to load the data.
*/
protected function wrapLoad(loadable:IEventDispatcher):void
{
_loadable = loadable;
_loadable.addEventListener(LoadSuccessEvent.SUCCESS, function(event:LoadSuccessEvent):void
{
loaded(_loadable);
}, false, 0, true);
_loadable.addEventListener(LoadFailedEvent.FAILED, function(event:LoadFailedEvent):void
{
failed(event.fault);
}, false, 0, true);
}

/**
* Called by sub-classes when the data for this association has been loaded. The loaded data will
* replace any data on the associated property.
*
* @param data The loaded data.
*/
protected function loaded(data:Object):void
private function loaded(data:*):void
{
owner[property] = data;
object = data;
_helper.loaded(data);
cleanupLoad();
_isLoaded = true;
}

/**
* Called during a load to create the request that will load the data for this association.
*
* @return A request.
*/
protected function createLoadRequest():AsyncRequest
{
throw new IllegalOperationError("Association.createLoadRequest() is not implemented.");
}

private function populateInverseRelationship(entity:Entity):void
Expand Down Expand Up @@ -236,20 +164,13 @@ package mesh.model.associations
return options.isLazy || options.lazy;
}

private var _isLoaded:Boolean;
/**
* Indicates if the data for this association has been loaded.
*/
public function get isLoaded():Boolean
{
return _helper.isLoaded;
}

/**
* Indicates if the association is loading its data.
*/
public function get isLoading():Boolean
{
return _helper.isLoading;
return !isLazy || _isLoaded;
}

/**
Expand Down
20 changes: 9 additions & 11 deletions src/mesh/model/associations/AssociationCollection.as
@@ -1,8 +1,8 @@
package mesh.model.associations
{
import mesh.model.Entity;
import mesh.model.store.AsyncRequest;
import mesh.model.store.Query;
import mesh.model.store.ResultList;

import mx.collections.ListCollectionView;
import mx.events.CollectionEvent;
Expand All @@ -25,6 +25,14 @@ package mesh.model.associations
_list.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleListCollectionChange);
}

/**
* @inheritDoc
*/
override protected function createLoadRequest():AsyncRequest
{
return owner.store.findAsync(query);
}

private function handleListCollectionChange(event:CollectionEvent):void
{
switch (event.kind) {
Expand Down Expand Up @@ -84,16 +92,6 @@ package mesh.model.associations
}
}

/**
* @inheritDoc
*/
override protected function executeLoad():void
{
var result:ResultList = owner.store.find(query);
wrapLoad(result);
if (result.isLoaded) loaded(result);
}

/**
* @inheritDoc
*/
Expand Down
27 changes: 13 additions & 14 deletions src/mesh/model/associations/HasAssociation.as
Expand Up @@ -3,6 +3,7 @@ package mesh.model.associations
import flash.errors.IllegalOperationError;

import mesh.model.Entity;
import mesh.model.store.AsyncRequest;

import mx.events.PropertyChangeEvent;

Expand All @@ -22,12 +23,6 @@ package mesh.model.associations
checkForRequiredFields();
}

private function checkForRequiredFields():void
{
if (entityType == null) throw new IllegalOperationError("Undefined entity type for " + this);
if (foreignKey != null && !owner.hasOwnProperty(foreignKey)) throw new IllegalOperationError("Undefined foreign key for " + this);
}

/**
* @inheritDoc
*/
Expand All @@ -38,21 +33,25 @@ package mesh.model.associations
entity.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, handleAssociatedEntityPropertyChange);
}

private function handleAssociatedEntityPropertyChange(event:PropertyChangeEvent):void
private function checkForRequiredFields():void
{
if (event.property == "id") {
populateForeignKey();
}
if (entityType == null) throw new IllegalOperationError("Undefined entity type for " + this);
if (foreignKey != null && !owner.hasOwnProperty(foreignKey)) throw new IllegalOperationError("Undefined foreign key for " + this);
}

/**
* @inheritDoc
*/
override protected function executeLoad():void
override protected function createLoadRequest():AsyncRequest
{
return owner.store.findAsync(entityType, owner[foreignKey]);
}

private function handleAssociatedEntityPropertyChange(event:PropertyChangeEvent):void
{
var entity:Entity = owner.store.find(entityType, owner[foreignKey]);
wrapLoad(entity);
if (entity.status.isSynced) loaded(entity);
if (event.property == "id") {
populateForeignKey();
}
}

private function populateForeignKey():void
Expand Down
35 changes: 0 additions & 35 deletions src/mesh/model/load/LoadEvent.as

This file was deleted.

0 comments on commit 3a8579e

Please sign in to comment.