Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/group mapping #7

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 43 additions & 12 deletions src/org/swiftsuspenders/Injector.as
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ package org.swiftsuspenders
import flash.events.EventDispatcher;
import flash.system.ApplicationDomain;
import flash.utils.Dictionary;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;

import org.swiftsuspenders.dependencyproviders.DependencyProvider;
Expand All @@ -22,6 +21,7 @@ package org.swiftsuspenders
import org.swiftsuspenders.errors.InjectorError;
import org.swiftsuspenders.errors.InjectorInterfaceConstructionError;
import org.swiftsuspenders.errors.InjectorMissingMappingError;
import org.swiftsuspenders.mapping.IInjectionMapping;
import org.swiftsuspenders.mapping.InjectionMapping;
import org.swiftsuspenders.mapping.MappingEvent;
import org.swiftsuspenders.reflection.DescribeTypeJSONReflector;
Expand Down Expand Up @@ -236,7 +236,7 @@ package org.swiftsuspenders
* @see #unmap()
* @see org.swiftsuspenders.mapping.InjectionMapping
*/
public function map(type : Class, name : String = '') : InjectionMapping
public function map(type : Class, name : String = '') : IInjectionMapping
{
const mappingId : String = getQualifiedClassName(type) + '|' + name;
return _mappings[mappingId] || createMapping(type, name, mappingId);
Expand All @@ -259,20 +259,12 @@ package org.swiftsuspenders
{
const mappingId : String = getQualifiedClassName(type) + '|' + name;
var mapping : InjectionMapping = _mappings[mappingId];
if (mapping && mapping.isSealed)
{
throw new InjectorError('Can\'t unmap a sealed mapping');
}
if (!mapping)
{
throw new InjectorError('Error while removing an injector mapping: ' +
'No mapping defined for dependency ' + mappingId);
}
mapping.getProvider().destroy();
delete _mappings[mappingId];
delete providerMappings[mappingId];
hasEventListener(MappingEvent.POST_MAPPING_REMOVE) && dispatchEvent(
new MappingEvent(MappingEvent.POST_MAPPING_REMOVE, type, name, null));
destroyMapping(mapping);
}

/**
Expand Down Expand Up @@ -325,7 +317,7 @@ package org.swiftsuspenders
* @throws org.swiftsuspenders.errors.InjectorMissingMappingError when no mapping was found
* for the specified dependency
*/
public function getMapping(type : Class, name : String = '') : InjectionMapping
public function getMapping(type : Class, name : String = '') : IInjectionMapping
{
const mappingId : String = getQualifiedClassName(type) + '|' + name;
var mapping : InjectionMapping = _mappings[mappingId];
Expand Down Expand Up @@ -547,6 +539,7 @@ package org.swiftsuspenders
{
_applicationDomain = applicationDomain || ApplicationDomain.currentDomain;
}

public function get applicationDomain() : ApplicationDomain
{
return _applicationDomain;
Expand Down Expand Up @@ -609,6 +602,30 @@ package org.swiftsuspenders
_blockParentFallbackProvider = value;
}

/**
* Removes all mapping linked to specified group.
* @param name
*
* @see org.swiftsuspenders.mapping.InjectionMapping#toGroup()
*/
public function unmapGroup(name : String) : void {
var mappingsToDestroy : Vector.<InjectionMapping> = new <InjectionMapping>[];
var mapping : InjectionMapping;
for (var mappingId : String in _mappings) {
mapping = _mappings[mappingId];
if (mapping.groupName == name) {
if (mapping.isSealed) {
throw new InjectorError('Can\'t unmap a sealed mapping');
} else {
mappingsToDestroy.push(mapping);
}
}
}
for each (mapping in mappingsToDestroy) {
destroyMapping(mapping);
}
}

//---------------------- Internal Methods ----------------------//
SsInternal static function purgeInjectionPointsCache() : void
{
Expand Down Expand Up @@ -718,5 +735,19 @@ package org.swiftsuspenders
hasEventListener(InjectionEvent.POST_CONSTRUCT) && dispatchEvent(
new InjectionEvent(InjectionEvent.POST_CONSTRUCT, target, targetType));
}

private function destroyMapping(mapping:InjectionMapping):void
{
if (mapping.isSealed)
{
throw new InjectorError('Can\'t unmap a sealed mapping');
}
mapping.getProvider().destroy();
delete _mappings[mapping.mappingId];
delete providerMappings[mapping.mappingId];
hasEventListener(MappingEvent.POST_MAPPING_REMOVE) && dispatchEvent(
new MappingEvent(MappingEvent.POST_MAPPING_REMOVE, mapping.type, mapping.name, null));
}

}
}
47 changes: 47 additions & 0 deletions src/org/swiftsuspenders/mapping/IInjectionMapping.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.swiftsuspenders.mapping {
import org.swiftsuspenders.Injector;
import org.swiftsuspenders.dependencyproviders.DependencyProvider;

public interface IInjectionMapping extends ProviderlessMapping
{
/**
* @copy InjectionMapping#softly()
*/
function softly() : ProviderlessMapping;

/**
* @copy InjectionMapping#locally()
*/
function locally() : ProviderlessMapping;

/**
* @copy InjectionMapping#toProviderOf()
*/
function toProviderOf(type : Class, name : String = '') : UnsealedMapping;

/**
* @copy InjectionMapping#unseal()
*/
function unseal(key : Object) : IInjectionMapping;

/**
* @copy InjectionMapping#isSealed()
*/
function get isSealed() : Boolean;

/**
* @copy InjectionMapping#setInjector()
*/
function setInjector(injector : Injector) : IInjectionMapping;

/**
* @copy InjectionMapping#getProvider()
*/
function getProvider() : DependencyProvider;

/**
* @copy InjectionMapping#hasProvider()
*/
function hasProvider() : Boolean;
}
}
35 changes: 31 additions & 4 deletions src/org/swiftsuspenders/mapping/InjectionMapping.as
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package org.swiftsuspenders.mapping
import org.swiftsuspenders.errors.InjectorError;
import org.swiftsuspenders.utils.SsInternal;

public class InjectionMapping implements ProviderlessMapping, UnsealedMapping
public class InjectionMapping implements IInjectionMapping
{
//---------------------- Private / Protected Properties ----------------------//
private var _type : Class;
Expand All @@ -33,6 +33,27 @@ package org.swiftsuspenders.mapping
private var _local : Boolean;
private var _sealed : Boolean;
private var _sealKey : Object;
private var _groupName : String;

//---------------------- Internal Properties ----------------------//
public function get type() : Class
{
return _type;
}

public function get name() : String
{
return _name;
}

public function get mappingId() : String
{
return _mappingId;
}

public function get groupName() : String {
return _groupName;
}

//---------------------- Public Methods ----------------------//
public function InjectionMapping(
Expand Down Expand Up @@ -184,7 +205,8 @@ package org.swiftsuspenders.mapping
* @throws org.swiftsuspenders.errors.InjectorMissingMappingError when no mapping was found
* for the specified dependency
*/
public function toProviderOf(type : Class, name:String = ''):UnsealedMapping{
public function toProviderOf(type : Class, name : String = '') : UnsealedMapping
{
const provider : DependencyProvider = _creatingInjector.getMapping(type, name).getProvider();
toProvider(provider);
return this;
Expand Down Expand Up @@ -277,7 +299,7 @@ package org.swiftsuspenders.mapping
*
* @see #seal()
*/
public function unseal(key : Object) : InjectionMapping
public function unseal(key : Object) : IInjectionMapping
{
if (!_sealed)
{
Expand Down Expand Up @@ -335,7 +357,7 @@ package org.swiftsuspenders.mapping
*
* @return The <code>InjectionMapping</code> the method is invoked on
*/
public function setInjector(injector : Injector) : InjectionMapping
public function setInjector(injector : Injector) : IInjectionMapping
{
_sealed && throwSealedError();
if (injector == _overridingInjector)
Expand All @@ -348,6 +370,11 @@ package org.swiftsuspenders.mapping
return this;
}

public function toGroup(name : String) : UnsealedMapping
{
_groupName = name;
return this;
}

//---------------------- Private / Protected Methods ----------------------//
private function mapProvider(provider : DependencyProvider) : void
Expand Down
6 changes: 1 addition & 5 deletions src/org/swiftsuspenders/mapping/ProviderlessMapping.as
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ package org.swiftsuspenders.mapping
{
import org.swiftsuspenders.dependencyproviders.DependencyProvider;

public interface ProviderlessMapping
public interface ProviderlessMapping extends UnsealedMapping
{
/**
* @copy InjectionMapping#toType()
Expand All @@ -36,9 +36,5 @@ package org.swiftsuspenders.mapping
*/
function toProvider(provider : DependencyProvider) : UnsealedMapping;

/**
* @copy InjectionMapping#seal()
*/
function seal() : Object;
}
}
5 changes: 5 additions & 0 deletions src/org/swiftsuspenders/mapping/UnsealedMapping.as
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ package org.swiftsuspenders.mapping
* @copy InjectionMapping#seal()
*/
function seal() : Object;

/**
* @copy InjectionMapping#toGroup()
*/
function toGroup(name : String) : UnsealedMapping;
}
}
3 changes: 2 additions & 1 deletion src/org/swiftsuspenders/reflection/ReflectorBase.as
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

package org.swiftsuspenders.reflection
{
import flash.display.Stage;
import flash.utils.Proxy;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
Expand All @@ -30,7 +31,7 @@ package org.swiftsuspenders.reflection
- int and uint return Number as their constructor
For these, we have to fall back to more verbose ways of getting the constructor.
*/
if (value is Proxy || value is Number || value is XML || value is XMLList || value is Vector.<*>)
if (value is Proxy || value is Number || value is XML || value is XMLList || value is Vector.<*> || value is Stage)
{
return Class(getDefinitionByName(getQualifiedClassName(value)));
}
Expand Down
16 changes: 7 additions & 9 deletions test/org/swiftsuspenders/ChildInjectorTests.as
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ package org.swiftsuspenders
{
import flexunit.framework.Assert;

import org.swiftsuspenders.mapping.InjectionMapping;

import org.swiftsuspenders.mapping.IInjectionMapping;
import org.swiftsuspenders.support.injectees.ClassInjectee;
import org.swiftsuspenders.support.injectees.childinjectors.ChildInjectorCreatingProvider;
import org.swiftsuspenders.support.injectees.childinjectors.InjectorInjectee;
Expand All @@ -26,7 +25,6 @@ package org.swiftsuspenders
import org.swiftsuspenders.support.types.Clazz;
import org.swiftsuspenders.support.types.Interface;
import org.swiftsuspenders.utils.SsInternal;
import org.swiftsuspenders.dependencyproviders.ClassProvider;

use namespace SsInternal;

Expand Down Expand Up @@ -61,13 +59,13 @@ package org.swiftsuspenders
{
injector.map(RobotFoot);

var leftFootMapping : InjectionMapping = injector.map(RobotLeg, 'leftLeg');
var leftFootMapping : IInjectionMapping = injector.map(RobotLeg, 'leftLeg');
var leftChildInjector : Injector = injector.createChildInjector();
leftChildInjector.map(RobotAnkle);
leftChildInjector.map(RobotFoot).toType(LeftRobotFoot);

leftFootMapping.setInjector(leftChildInjector);
var rightFootMapping : InjectionMapping = injector.map(RobotLeg, 'rightLeg');
var rightFootMapping : IInjectionMapping = injector.map(RobotLeg, 'rightLeg');
var rightChildInjector : Injector = injector.createChildInjector();
rightChildInjector.map(RobotAnkle);
rightChildInjector.map(RobotFoot).toType(RightRobotFoot);
Expand All @@ -87,13 +85,13 @@ package org.swiftsuspenders
injector.map(RobotFoot);
injector.map(RobotToes);

var leftFootMapping : InjectionMapping = injector.map(RobotLeg, 'leftLeg');
var leftFootMapping : IInjectionMapping = injector.map(RobotLeg, 'leftLeg');
var leftChildInjector : Injector = injector.createChildInjector();
leftChildInjector.map(RobotAnkle);
leftChildInjector.map(RobotFoot).toType(LeftRobotFoot);
leftFootMapping.setInjector(leftChildInjector);

var rightFootMapping : InjectionMapping = injector.map(RobotLeg, 'rightLeg');
var rightFootMapping : IInjectionMapping = injector.map(RobotLeg, 'rightLeg');
var rightChildInjector : Injector = injector.createChildInjector();
rightChildInjector.map(RobotAnkle);
rightChildInjector.map(RobotFoot).toType(RightRobotFoot);
Expand Down Expand Up @@ -130,12 +128,12 @@ package org.swiftsuspenders
injector.map(RobotFoot);
injector.map(RobotToes);

var leftFootMapping : InjectionMapping = injector.map(RobotLeg, 'leftLeg');
var leftFootMapping : IInjectionMapping = injector.map(RobotLeg, 'leftLeg');
var leftChildInjector : Injector = injector.createChildInjector();
leftChildInjector.map(RobotFoot).toType(LeftRobotFoot);
leftFootMapping.setInjector(leftChildInjector);

var rightFootMapping : InjectionMapping = injector.map(RobotLeg, 'rightLeg');
var rightFootMapping : IInjectionMapping = injector.map(RobotLeg, 'rightLeg');
var rightChildInjector : Injector = injector.createChildInjector();
rightChildInjector.map(RobotFoot).toType(RightRobotFoot);
rightFootMapping.setInjector(rightChildInjector);
Expand Down
20 changes: 17 additions & 3 deletions test/org/swiftsuspenders/InjectorTests.as
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ package org.swiftsuspenders
[Test]
public function unmap_removes_mapping():void
{
var injectee:InterfaceInjectee = new InterfaceInjectee();
var value:Clazz = new Clazz();
injector.map(Interface).toValue(value);
Assert.assertTrue(injector.satisfies(Interface));
Expand Down Expand Up @@ -1165,7 +1164,7 @@ package org.swiftsuspenders
[Test]
public function performMappedMappingInjection():void
{
var mapping : InjectionMapping = injector.map(Interface);
var mapping : InjectionMapping = injector.map(Interface) as InjectionMapping;
mapping.toSingleton(Clazz);
injector.map(Interface2).toProvider(new OtherMappingProvider(mapping));
var injectee:MultipleSingletonsOfSameClassInjectee = injector.instantiateUnmapped(MultipleSingletonsOfSameClassInjectee);
Expand All @@ -1177,7 +1176,7 @@ package org.swiftsuspenders
[Test]
public function performMappedNamedMappingInjection():void
{
var mapping : InjectionMapping = injector.map(Interface);
var mapping : InjectionMapping = injector.map(Interface) as InjectionMapping;
mapping.toSingleton(Clazz);
injector.map(Interface2).toProvider(new OtherMappingProvider(mapping));
injector.map(Interface, 'name1').toProvider(new OtherMappingProvider(mapping));
Expand Down Expand Up @@ -1277,5 +1276,20 @@ package org.swiftsuspenders
injector.map(SingletonInjectee).toSingleton(SingletonInjectee, true);
Assert.assertTrue("SingletonInjectee#hasInitialized", SingletonInjectee.hasInitialized);
}

[Test]
public function unmap_group() : void {
var groupName : String = "test";
injector.map(Interface, "value").toValue(new Clazz()).toGroup(groupName);
injector.map(Interface, "singleton").toSingleton(Clazz).toGroup(groupName);
injector.map(Interface).toSingleton(Clazz);
Assert.assertTrue(injector.satisfies(Interface, "value"));
Assert.assertTrue(injector.satisfies(Interface, "singleton"));
Assert.assertTrue(injector.satisfies(Interface));
injector.unmapGroup(groupName);
Assert.assertFalse("Mapping should be removed", injector.satisfies(Interface, "value"));
Assert.assertFalse("Mapping should be removed", injector.satisfies(Interface, "singleton"));
Assert.assertTrue("Mapping should exist", injector.satisfies(Interface));
}
}
}