Skip to content

Commit

Permalink
starting rework on association refactoring:
Browse files Browse the repository at this point in the history
- renaming relationships to definitions
- removing proxy methods from entity.
- adding instance methods to generate and retrieve associations.
  • Loading branch information
danschultz committed Apr 7, 2011
1 parent 65e4740 commit 71be012
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 436 deletions.
426 changes: 101 additions & 325 deletions src/mesh/Entity.as

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions src/mesh/EntityDescription.as
Expand Up @@ -13,9 +13,9 @@ package mesh

import mesh.adaptors.ServiceAdaptor;
import mesh.associations.BelongsToRelationship;
import mesh.associations.HasManyRelationship;
import mesh.associations.HasOneRelationship;
import mesh.associations.Relationship;
import mesh.associations.HasManyDefinition;
import mesh.associations.HasOneDefinition;
import mesh.associations.AssociationDefinition;
import mesh.core.reflection.clazz;
import mesh.core.reflection.newInstance;

Expand All @@ -24,8 +24,8 @@ package mesh
public class EntityDescription
{
private static const RELATIONSHIPS:Object = {
HasMany: HasManyRelationship,
HasOne: HasOneRelationship,
HasMany: HasManyDefinition,
HasOne: HasOneDefinition,
BelongsTo: BelongsToRelationship
};

Expand Down Expand Up @@ -85,7 +85,7 @@ package mesh

public function addRelationships(...relationships):void
{
for each (var relationship:Relationship in relationships) {
for each (var relationship:AssociationDefinition in relationships) {
_relationships.add(relationship);
_propertyToRelationship.put(relationship.property, relationship);
}
Expand All @@ -101,7 +101,7 @@ package mesh
return _propertyToAggregate.grab(property);
}

public function getRelationshipForProperty(property:String):Relationship
public function getRelationshipForProperty(property:String):AssociationDefinition
{
return _propertyToRelationship.grab(property);
}
Expand Down Expand Up @@ -315,7 +315,7 @@ package mesh
_properties.addAll(aggregate.properties);
}

for each (var relationship:Relationship in relationships) {
for each (var relationship:AssociationDefinition in relationships) {
_properties.addAll(relationship.properties);
}

Expand Down
4 changes: 2 additions & 2 deletions src/mesh/SaveBatch.as
Expand Up @@ -109,7 +109,7 @@ import collections.HashSet;
import mesh.Entity;
import mesh.EntityDescription;
import mesh.associations.BelongsToRelationship;
import mesh.associations.Relationship;
import mesh.associations.AssociationDefinition;
import mesh.core.string.capitalize;

import operations.EmptyOperation;
Expand All @@ -134,7 +134,7 @@ class PersistenceCache
private function countLongestParentPath(description:EntityDescription):int
{
var count:int = 0;
for each (var relationship:Relationship in description.relationships) {
for each (var relationship:AssociationDefinition in description.relationships) {
if (relationship is BelongsToRelationship) {
count = Math.max(count, countLongestParentPath(EntityDescription.describe(relationship.target)) + 1);
}
Expand Down
@@ -1,13 +1,10 @@
package mesh.associations
{
import collections.HashMap;

import flash.errors.IllegalOperationError;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.utils.Proxy;
import flash.utils.describeType;
import flash.utils.flash_proxy;
import flash.utils.setTimeout;

Expand All @@ -17,7 +14,6 @@ package mesh.associations
import mesh.Mesh;
import mesh.SaveBatch;
import mesh.core.reflection.className;
import mesh.core.reflection.clazz;

import mx.events.PropertyChangeEvent;

Expand All @@ -27,13 +23,13 @@ package mesh.associations
import operations.ResultOperationEvent;

/**
* An association proxy is a class that contains the references to the objects in
* a relationship, where the <em>owner</em> represents the object hosting the
* association, and the <em>target</em> is the actual associated object.
* 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,
* and the <em>target</em> is the actual associated object.
*
* @author Dan Schultz
*/
public dynamic class AssociationProxy extends Proxy implements IEventDispatcher, IPersistable
public dynamic class Association extends Proxy implements IEventDispatcher, IPersistable
{
private var _dispatcher:EventDispatcher;
private var _callbacks:Callbacks = new Callbacks();
Expand All @@ -44,36 +40,28 @@ package mesh.associations
* @param owner The parent that owns the relationship.
* @param relationship The relationship being represented by the proxy.
*/
public function AssociationProxy(owner:Entity, relationship:Relationship)
public function Association(owner:Entity, definition:AssociationDefinition)
{
super();
_dispatcher = new EventDispatcher(this);
_owner = owner;
_relationship = relationship;

beforeLoad(function(proxy:AssociationProxy):void
{
setBindableProperty("isLoading", function():Boolean { return isLoading; }, function():void { _isLoading = true; });
});
_definition = definition;

afterLoad(function(proxy:AssociationProxy):void
{
setBindableProperty("isLoaded", function():Boolean { return isLoaded; }, function():void { _isLoaded = true; });
setBindableProperty("isLoading", function():Boolean { return isLoading; }, function():void { _isLoading = false; });
});
beforeLoad(loading);
afterLoad(loaded);
}

private function addCallback(method:String, block:Function):void
{
_callbacks.addCallback(method, block, [this]);
_callbacks.addCallback(method, block);
}

public function beforeLoad(block:Function):void
protected function beforeLoad(block:Function):void
{
addCallback("beforeLoad", block);
}

public function afterLoad(block:Function):void
protected function afterLoad(block:Function):void
{
addCallback("afterLoad", block);
}
Expand All @@ -83,51 +71,19 @@ package mesh.associations
_callbacks.callback(method);
}

public function fromVO(vo:Object, options:Object = null):void
{

}

private static const VO_TO_ENTITY:HashMap = new HashMap();
protected function createEntityFromVOMapping(vo:Object, options:Object = null):Entity
{
var voType:Class = clazz(vo);
if (!VO_TO_ENTITY.containsKey(voType)) {
for each (var metadataXML:XML in describeType(vo)..metadata.(@name == "Entity")) {
VO_TO_ENTITY.put(voType, metadataXML.parent().@type);
break;
}
}

var entityType:Class = VO_TO_ENTITY.grab(voType);
if (entityType == null) {
throw new IllegalOperationError("Entity mapping not found for " + className(vo));
}

var entity:Entity = new entityType();
entity.fromVO(vo, options);
return entity;
}

/**
* Executes an operation that will load the target for this association.
*
* @return An executing operation.
*/
final public function load():Operation
{
var operation:Operation = isLoaded ? new EmptyOperation() : createLoad();
setTimeout(operation.execute, 50);
var operation:Operation = (isLoaded || isLoading) ? new EmptyOperation() : createLoad();
setTimeout(operation.execute, Mesh.DELAY);
return operation;
}

/**
* Generates an unexecuted operation that will be used to load the target of the
* association.
*
* @return An unexecuted operation.
*/
public function createLoad():Operation
private function createLoad():Operation
{
var operation:Operation = createLoadOperation();
operation.addEventListener(ResultOperationEvent.RESULT, function(event:ResultOperationEvent):void
Expand All @@ -141,20 +97,22 @@ package mesh.associations
return operation;
}

/**
* Called by <code>createLoad()</code> to generate a query operation that is specific for this
* association. This method must be overridden and implemented by each association.
*
* @return An unexecuted operation.
*/
protected function createLoadOperation():Operation
private function loading():void
{
throw new IllegalOperationError(className(this) + ".createLoadOperation() is not implemented.");
if (!_isLoading) {
_isLoading = true;
dispatchEvent( PropertyChangeEvent.createUpdateEvent(this, "isLoading", false, true) );
}
}

public function loaded():void
private function loaded():void
{
callback("afterLoad");
if (!_isLoaded) {
_isLoaded = true;
_isLoading = false;
dispatchEvent( PropertyChangeEvent.createUpdateEvent(this, "isLoading", true, false) );
dispatchEvent( PropertyChangeEvent.createUpdateEvent(this, "isLoaded", false, true) );
}
}

/**
Expand All @@ -165,8 +123,8 @@ package mesh.associations
*/
protected function populateBelongsToAssociation(entity:Entity):void
{
for each (var association:AssociationProxy in entity.associations) {
if (association is BelongsToAssociation && relationship.target == association.relationship.owner) {
for each (var association:Association in entity.associations) {
if (association is BelongsToAssociation && definition.target == association.definition.owner) {
association.target = owner;
break;
}
Expand Down Expand Up @@ -236,13 +194,13 @@ package mesh.associations
return _isLoading;
}

private var _relationship:Relationship;
private var _definition:AssociationDefinition;
/**
* The relationship model that this association represents.
*/
public function get relationship():Relationship
public function get definition():AssociationDefinition
{
return _relationship;
return _definition;
}

private var _owner:Entity;
Expand Down
4 changes: 2 additions & 2 deletions src/mesh/associations/AssociationCollection.as
Expand Up @@ -24,7 +24,7 @@ package mesh.associations

use namespace flash_proxy;

public dynamic class AssociationCollection extends AssociationProxy implements IList
public dynamic class AssociationCollection extends Association implements IList
{
private var _originalEntities:ArraySequence;
private var _mirroredEntities:ArraySequence;
Expand All @@ -33,7 +33,7 @@ package mesh.associations
/**
* @copy AssociationProxy#AssociationProxy()
*/
public function AssociationCollection(source:Entity, relationship:Relationship)
public function AssociationCollection(source:Entity, relationship:AssociationDefinition)
{
super(source, relationship);
target = [];
Expand Down
Expand Up @@ -22,7 +22,7 @@ package mesh.associations
*
* @author Dan Schultz
*/
public dynamic class Relationship extends Proxy
public dynamic class AssociationDefinition extends Proxy
{
/**
* Constructor.
Expand All @@ -32,7 +32,7 @@ package mesh.associations
* @param target The destination of the association.
* @param options A set of options defined for this relationship.
*/
public function Relationship(owner:Class, property:String, target:Class, options:Object)
public function AssociationDefinition(owner:Class, property:String, target:Class, options:Object)
{
if (property == null || property.length == 0) {
throw new ArgumentError("Missing property for '" + humanize(className(this)).toLowerCase() + "' on " + className(owner));
Expand All @@ -55,8 +55,8 @@ package mesh.associations
*/
public function createProxy(entity:Entity):*
{
var associationClassName:String = getQualifiedClassName(this).replace("Relationship", "Association");
var proxy:AssociationProxy = newInstance(getDefinitionByName(associationClassName) as Class, entity, this);
var associationClassName:String = getQualifiedClassName(this).replace("Definition", "Association");
var proxy:Association = newInstance(getDefinitionByName(associationClassName) as Class, entity, this);
if (proxy == null) {
throw new IllegalOperationError("Could not find proxy for " + className(this));
}
Expand All @@ -69,7 +69,7 @@ package mesh.associations
* @param relationship The relationship to check with.
* @return <code>true</code> if the two are equal.
*/
public function equals(relationship:Relationship):Boolean
public function equals(relationship:AssociationDefinition):Boolean
{
return relationship != null &&
owner == relationship.owner &&
Expand Down Expand Up @@ -175,7 +175,7 @@ package mesh.associations
{
// supports calls like: relationship.isHasOne, or relationship.isHasMany.
if (name.toString().indexOf("is") == 0) {
return camelize(name.toString().replace("is", ""), false) == className(this).replace(className(Relationship), "");
return camelize(name.toString().replace("is", ""), false) == className(this).replace(className(AssociationDefinition), "");
}

// supports calls like: relationship.hasLazy
Expand Down
4 changes: 2 additions & 2 deletions src/mesh/associations/BelongsToAssociation.as
Expand Up @@ -11,7 +11,7 @@ package mesh.associations
/**
* @copy AssociationProxy#AssociationProxy()
*/
public function BelongsToAssociation(owner:Entity, relationship:Relationship)
public function BelongsToAssociation(owner:Entity, relationship:AssociationDefinition)
{
super(owner, relationship);
}
Expand All @@ -21,7 +21,7 @@ package mesh.associations
*/
override protected function createLoadOperation():Operation
{
var operation:Operation = Query.entity(relationship.target).find(owner[BelongsToRelationship( relationship ).foreignKey]);
var operation:Operation = Query.entity(definition.target).find(owner[BelongsToRelationship( definition ).foreignKey]);
operation.addEventListener(ResultOperationEvent.RESULT, function(event:ResultOperationEvent):void
{
event.data = event.data[0];
Expand Down
2 changes: 1 addition & 1 deletion src/mesh/associations/BelongsToRelationship.as
Expand Up @@ -7,7 +7,7 @@ package mesh.associations
*
* @author Dan Schultz
*/
public class BelongsToRelationship extends HasOneRelationship
public class BelongsToRelationship extends HasOneDefinition
{
/**
* @copy Relationship#Relationship()
Expand Down
4 changes: 2 additions & 2 deletions src/mesh/associations/HasAssociation.as
Expand Up @@ -2,12 +2,12 @@ package mesh.associations
{
import mesh.Entity;

public class HasAssociation extends AssociationProxy
public class HasAssociation extends Association
{
/**
* @copy AssociationProxy#AssociationProxy()
*/
public function HasAssociation(owner:Entity, relationship:Relationship)
public function HasAssociation(owner:Entity, relationship:AssociationDefinition)
{
super(owner, relationship);

Expand Down
6 changes: 3 additions & 3 deletions src/mesh/associations/HasManyAssociation.as
Expand Up @@ -12,7 +12,7 @@ package mesh.associations
/**
* @copy AssociationCollection#AssociationCollection()
*/
public function HasManyAssociation(source:Entity, relationship:Relationship)
public function HasManyAssociation(source:Entity, relationship:AssociationDefinition)
{
super(source, relationship);
}
Expand All @@ -23,9 +23,9 @@ package mesh.associations
override protected function createLoadOperation():Operation
{
var options:Object = {};
options[camelize(className(relationship.owner), false)] = owner;
options[camelize(className(definition.owner), false)] = owner;

return Query.entity(relationship.target).where(options);
return Query.entity(definition.target).where(options);
}

/**
Expand Down

0 comments on commit 71be012

Please sign in to comment.