Skip to content

Commit

Permalink
Add mapping from an Entity to a data source
Browse files Browse the repository at this point in the history
  • Loading branch information
danschultz committed Jul 28, 2011
1 parent 87cedf9 commit c426dd5
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 8 deletions.
148 changes: 148 additions & 0 deletions src/mesh/source/MultiSource.as
@@ -1,12 +1,160 @@
package mesh.source
{
import flash.errors.IllegalOperationError;
import flash.utils.Dictionary;

import mesh.core.reflection.reflect;
import mesh.model.Entity;
import mesh.model.Store;

/**
* An entity source that maps a type of entity to its source.
*
* <p>
* This source respects the inhertence of entities. For instance, say you have
* entity <code>A</code>, and entity <code>B</code> that extends from <code>A</code>.
* If you map <code>A</code> to an source, then <code>B</code> will use the same
* source as <code>A</code>.
* </p>
*
* @author Dan Schultz
*/
public class MultiSource extends Source
{
private var _mapping:Dictionary = new Dictionary();

/**
* Constructor.
*/
public function MultiSource()
{
super();
}

/**
* Maps an entity type to an entity source. This source respects the inhertence
* of entities. For instance, say you have entity <code>A</code>, and entity
* <code>B</code> that extends from <code>A</code>. If you map <code>A</code> to
* an source, then <code>B</code> will use the same source as <code>A</code>.
*
* @param entity The entity type to map.
* @param source The source to use for the entity.
*/
public function map(entity:Class, source:Source):void
{
_mapping[entity] = source;
}

/**
* @inheritDoc
*/
override public function create(store:Store, entity:Entity):void
{
invoke(store, "create", entity);
}

/**
* @inheritDoc
*/
override public function createEach(store:Store, entities:Array):void
{
invokeEach(store, "createEach", entities);
}

/**
* @inheritDoc
*/
override public function destroy(store:Store, entity:Entity):void
{
invoke(store, "destroy", entity);
}

/**
* @inheritDoc
*/
override public function destroyEach(store:Store, entities:Array):void
{
invokeEach(store, "destroyEach", entities);
}

/**
* @inheritDoc
*/
override public function retrieve(store:Store, entity:Entity):void
{
invoke(store, "retrieve", entity);
}

/**
* @inheritDoc
*/
override public function retrieveEach(store:Store, entities:Array):void
{
invokeEach(store, "retrieveEach", entities);
}

/**
* @inheritDoc
*/
override public function update(store:Store, entity:Entity):void
{
invoke(store, "update", entity);
}

/**
* @inheritDoc
*/
override public function updateEach(store:Store, entities:Array):void
{
invokeEach(store, "updateEach", entities);
}

/**
* Returns the entity source that is mapped to the given entity. If no source is
* mapped, then <code>null</code> is returned.
*
* @param entity The entity type to get the source for.
* @return The source mapped to the given entity.
*/
protected function sourceFor(entity:Class):Source
{
return _mapping[entity];
}

private function invoke(store:Store, method:String, entity:Entity):void
{
var type:Class = entity.reflect.clazz;
throwIfUnmapped(type);
sourceFor(type)[method](store, entity);
}

private function invokeEach(store:Store, method:String, entities:Array):void
{
var grouped:Dictionary = groupByType(entities);
for (var type:Class in grouped) {
throwIfUnmapped(type);
sourceFor(type)[method](store, grouped[type]);
}
}

private function groupByType(entities:Array):Dictionary
{
var result:Dictionary = new Dictionary();
for each (var entity:Entity in entities) {
var type:Class = entity.reflect.clazz;
if (result[type] == null) {
result[type] = [];
}
result[type].push(entity);
}
return result;
}

private function throwIfUnmapped(entity:Class):void
{
if (sourceFor(entity) == null) {
throw new IllegalOperationError("Source undefined for " + reflect(entity).name);
}
}
}
}
16 changes: 8 additions & 8 deletions src/mesh/source/Source.as
Expand Up @@ -43,7 +43,7 @@ package mesh.source

public function create(store:Store, entity:Entity):void
{
throw new IllegalOperationError("EntitySource.createEntity() is not implemented.");
throw new IllegalOperationError("EntitySource.create() is not implemented.");
}

public function createEach(store:Store, entities:Array):void
Expand All @@ -55,7 +55,7 @@ package mesh.source

public function destroy(store:Store, entity:Entity):void
{
throw new IllegalOperationError("EntitySource.destroyEntity() is not implemented.");
throw new IllegalOperationError("EntitySource.destroy() is not implemented.");
}

public function destroyEach(store:Store, entities:Array):void
Expand All @@ -70,21 +70,21 @@ package mesh.source
throw new IllegalOperationError("EntitySource.fetch() is not implemented.");
}

public function retrieve(store:Store, id:*):void
public function retrieve(store:Store, entity:Entity):void
{
throw new IllegalOperationError("EntitySource.retrieveEntity() is not implemented.");
throw new IllegalOperationError("EntitySource.retrieve() is not implemented.");
}

public function retrieveEach(store:Store, ids:Array):void
public function retrieveEach(store:Store, entities:Array):void
{
for each (var id:* in ids) {
retrieve(store, id);
for each (var entity:Entity in entities) {
retrieve(store, entity);
}
}

public function update(store:Store, entity:Entity):void
{
throw new IllegalOperationError("EntitySource.updateEntity() is not implemented.");
throw new IllegalOperationError("EntitySource.update() is not implemented.");
}

public function updateEach(store:Store, entities:Array):void
Expand Down

0 comments on commit c426dd5

Please sign in to comment.