Skip to content

Commit

Permalink
Introduce infrastructure components
Browse files Browse the repository at this point in the history
  • Loading branch information
Erik Sundin committed Sep 7, 2013
1 parent 294e523 commit 201b25d
Show file tree
Hide file tree
Showing 27 changed files with 12,593 additions and 3,385 deletions.
24 changes: 24 additions & 0 deletions Source/Component/TyphoonDefinition+Infrastructure.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
////////////////////////////////////////////////////////////////////////////////
//
// TYPHOON FRAMEWORK
// Copyright 2013, Jasper Blues & Contributors
// All Rights Reserved.
//
// NOTICE: The authors permit you to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////

#import "TyphoonDefinition.h"

@class TyphoonPropertyPlaceholderConfigurer;
@protocol TyphoonResource;

/**
Declares short-hand definition factory methods for infrastructure components.
*/
@interface TyphoonDefinition (Infrastructure)

+ (TyphoonDefinition*)propertyPlaceholderWithResource:(id<TyphoonResource>)resource;

@end
38 changes: 38 additions & 0 deletions Source/Component/TyphoonDefinition+Infrastructure.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
////////////////////////////////////////////////////////////////////////////////
//
// TYPHOON FRAMEWORK
// Copyright 2013, Jasper Blues & Contributors
// All Rights Reserved.
//
// NOTICE: The authors permit you to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////


#import "TyphoonDefinition+Infrastructure.h"
#import "TyphoonPropertyPlaceholderConfigurer.h"
#import "TyphoonResource.h"
#import "TyphoonInitializer.h"

@implementation TyphoonDefinition (Infrastructure)

+ (NSString *)generateInfrastructureComponentKey {
CFUUIDRef uuid = CFUUIDCreate(NULL);
NSString *UUID = CFBridgingRelease(CFUUIDCreateString(NULL, uuid));
return UUID;
}

+ (TyphoonDefinition *)propertyPlaceholderWithResource:(id<TyphoonResource>)resource {

TyphoonDefinition *definition = [self withClass:[TyphoonPropertyPlaceholderConfigurer class] initialization:^(TyphoonInitializer *initializer) {

initializer.selector = @selector(configurerWithResource:);
[initializer injectWithObject:resource];

}];
definition.key = [self generateInfrastructureComponentKey];
return definition;
}

@end
7 changes: 2 additions & 5 deletions Source/Factory/Block/TyphoonBlockComponentFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,8 @@ - (id)initWithAssembly:(TyphoonAssembly*)assembly;
{
[self applyBeforeAdviceToAssemblyMethods:assembly];
NSArray* definitions = [self definitionsByPopulatingCache:assembly];
for (TyphoonDefinition* definition in definitions)
{
[self register:definition];
}
}
[self registerDefinitions:definitions];
}
return self;
}

Expand Down
10 changes: 10 additions & 0 deletions Source/Factory/TyphoonComponentFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
*/
@property (nonatomic, assign, getter = isLoaded) BOOL loaded;

/**
* The attached mutators.
*/
@property (nonatomic, strong, readonly) NSArray *mutators;

/**
* Mutate the component definitions with the mutators and
* build the not-lazy singletons.
Expand Down Expand Up @@ -69,6 +74,11 @@
*/
- (void) register:(TyphoonDefinition*)definition;

/**
* Registers a collection of components into the factory.
*/
- (void)registerDefinitions:(NSArray*)definitions;

/**
* Returns an an instance of the component matching the supplied class or protocol. For example:
Expand Down
33 changes: 33 additions & 0 deletions Source/Factory/TyphoonComponentFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ - (void)unload
}
}


- (void)registerDefinitions:(NSArray *)definitions {

NSArray *filteredDefintions = [self filterAndRegisterInfrastructureDefinitions:definitions];
for (TyphoonDefinition *definition in filteredDefintions) {
[self register:definition];
}

}

- (void)register:(TyphoonDefinition*)definition
{
if ([definition.key length] == 0)
Expand Down Expand Up @@ -241,6 +251,29 @@ - (NSString*)description
/* ====================================================================================================================================== */
#pragma mark - Private Methods

- (BOOL)isInfrastructureDefinition:(TyphoonDefinition *)definition {
return [definition.type conformsToProtocol:@protocol(TyphoonComponentFactoryMutator)];
}

- (void)registerInfrastructureDefinition:(TyphoonDefinition *)definition {
if ([definition.type conformsToProtocol:@protocol(TyphoonComponentFactoryMutator)]) {
[self attachMutator:[self objectForDefinition:definition]];
}
}

- (NSArray *)filterAndRegisterInfrastructureDefinitions:(NSArray *)definitions {
NSMutableArray *filteredDefintions = [[NSMutableArray alloc] initWithArray:definitions];

for (TyphoonDefinition *definition in definitions) {
if ([self isInfrastructureDefinition:definition]) {
[self registerInfrastructureDefinition:definition];
[filteredDefintions removeObject:definition];
}
}

return filteredDefintions;
}

- (id)objectForDefinition:(TyphoonDefinition*)definition
{
if (definition.scope == TyphoonScopeSingleton)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

@interface TyphoonRXMLElement (XmlComponentFactory)

- (BOOL)isComponent;

- (TyphoonDefinition*)asComponentDefinition;

Expand Down
70 changes: 51 additions & 19 deletions Source/Factory/Xml/TyphoonRXMLElement+XmlComponentFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,46 @@
#import "TyphoonDefinition+InstanceBuilder.h"
#import "TyphoonPropertyInjectedAsCollection.h"
#import "TyphoonParameterInjectedAsCollection.h"
#import "TyphoonDefinition+Infrastructure.h"
#import "TyphoonBundleResource.h"

@implementation TyphoonRXMLElement (XmlComponentFactory)

- (BOOL)isComponent {
return [[self tag] isEqualToString:@"component"] || [self isInfrastructureComponent];
}

- (TyphoonDefinition*)asComponentDefinition
{
[self assertTagName:@"component"];
Class clazz = NSClassFromString([self attribute:@"class"]);
if (clazz == nil)
if ([self isInfrastructureComponent])
{
return [self asInfrastructureDefinition];
}
else
{
[self assertTagName:@"component"];
Class clazz = NSClassFromString([self attribute:@"class"]);
if (clazz == nil)
{
[NSException raise:NSInvalidArgumentException format:@"Class '%@' can't be resolved.", [self attribute:@"class"]];
}

NSString* key = [self attribute:@"key"];
NSString* factory = [self attributeOrNilIfEmpty:@"factory-component"];
TyphoonScope scope = [self scopeForStringValue:[[self attribute:@"scope"] lowercaseString]];
BOOL isLazy = (scope == TyphoonScopeSingleton) && [self attributeAsBool:@"lazy-init"];
// Don't throw exception if a lazy init is set to a prototype.
// Even if the input is wrong, this won't set the definition
// in an unstable statement.

TyphoonDefinition* definition = [[TyphoonDefinition alloc] initWithClass:clazz key:key factoryComponent:factory];
[definition setBeforePropertyInjection:NSSelectorFromString([self attribute:@"before-property-injection"])];
[definition setAfterPropertyInjection:NSSelectorFromString([self attribute:@"after-property-injection"])];
[definition setLazy:isLazy];
[definition setScope:scope];
[self parseComponentDefinitionChildren:definition];
return definition;
}

NSString* key = [self attribute:@"key"];
NSString* factory = [self attributeOrNilIfEmpty:@"factory-component"];
TyphoonScope scope = [self scopeForStringValue:[[self attribute:@"scope"] lowercaseString]];
BOOL isLazy = (scope == TyphoonScopeSingleton) && [self attributeAsBool:@"lazy-init"];
// Don't throw exception if a lazy init is set to a prototype.
// Even if the input is wrong, this won't set the definition
// in an unstable statement.

TyphoonDefinition* definition = [[TyphoonDefinition alloc] initWithClass:clazz key:key factoryComponent:factory];
[definition setBeforePropertyInjection:NSSelectorFromString([self attribute:@"before-property-injection"])];
[definition setAfterPropertyInjection:NSSelectorFromString([self attribute:@"after-property-injection"])];
[definition setLazy:isLazy];
[definition setScope:scope];
[self parseComponentDefinitionChildren:definition];
return definition;
}

//TODO: Method too long, clean it up.
Expand Down Expand Up @@ -141,6 +154,25 @@ - (TyphoonInitializer*)asInitializer
/* ====================================================================================================================================== */
#pragma mark - Private Methods

- (BOOL)isInfrastructureComponent {
return [[self tag] isEqualToString:@"property-placeholder"];
}

- (TyphoonDefinition*)asInfrastructureDefinition
{
TyphoonDefinition *definition = nil;

if ([[self tag] isEqualToString:@"property-placeholder"]) {
NSString *location = [self attribute:@"location"];
if (location == nil) {
[NSException raise:NSInvalidArgumentException format:@"%@ is missing 'location' attribute.", [self tag]];
}
definition = [TyphoonDefinition propertyPlaceholderWithResource:[TyphoonBundleResource withName:location]];
}

return definition;
}

- (void)assertTagName:(NSString*)tagName
{
if (![self.tag isEqualToString:tagName])
Expand Down
10 changes: 7 additions & 3 deletions Source/Factory/Xml/TyphoonXmlComponentFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,23 @@ - (id)initWithConfigFileNames:(NSString*)configFileName, ...

- (void)parseComponentDefinitions
{
NSMutableArray *definitions = [[NSMutableArray alloc] init];

for (NSString* resourceName in _resourceNames)
{
NSString* xmlString = [[TyphoonBundleResource withName:resourceName] asString];
TyphoonRXMLElement* element = [TyphoonRXMLElement elementFromXMLString:xmlString encoding:NSUTF8StringEncoding];

[element iterate:@"*" usingBlock:^(TyphoonRXMLElement* child)
{
if ([[child tag] isEqualToString:@"component"])
if ([child isComponent])
{
[self register:[child asComponentDefinition]];
[definitions addObject:[child asComponentDefinition]];
}
}];
}

[self registerDefinitions:definitions];
}


Expand Down
1 change: 1 addition & 0 deletions Source/Typhoon.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
////////////////////////////////////////////////////////////////////////////////

#import "TyphoonDefinition.h"
#import "TyphoonDefinition+Infrastructure.h"
#import "TyphoonInitializer.h"
#import "TyphoonPropertyPlaceholderConfigurer.h"
#import "TyphoonResource.h"
Expand Down
17 changes: 17 additions & 0 deletions Tests/Factory/Block/InfrastructureComponentsAssembly.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// InfrastructureComponentsAssembly.h
// Tests
//
// Created by Erik Sundin on 9/7/13.
//
//

#import "TyphoonAssembly.h"

@interface InfrastructureComponentsAssembly : TyphoonAssembly

- (id)propertyPlaceHolderConfigurer;

- (id)knight;

@end
27 changes: 27 additions & 0 deletions Tests/Factory/Block/InfrastructureComponentsAssembly.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// InfrastructureComponentsAssembly.m
// Tests
//
// Created by Erik Sundin on 9/7/13.
//
//

#import "InfrastructureComponentsAssembly.h"
#import "Typhoon.h"
#import "Knight.h"

@implementation InfrastructureComponentsAssembly

- (id)propertyPlaceHolderConfigurer
{
return [TyphoonDefinition propertyPlaceholderWithResource:[TyphoonBundleResource withName:@"SomeProperties.properties"]];
}

- (id)knight
{
return [TyphoonDefinition withClass:[Knight class] properties:^(TyphoonDefinition *definition) {
[definition injectProperty:@selector(damselsRescued) withValueAsText:@"${damsels.rescued}"];
}];
}

@end
3 changes: 3 additions & 0 deletions Tests/Factory/Block/TyphoonBlockComponentFactoryTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#import "SingletonsChainAssembly.h"
#import "CavalryMan.h"
#import "OCLogTemplate.h"
#import "InfrastructureComponentsAssembly.h"

@interface TyphoonBlockComponentFactoryTests : TyphoonSharedComponentFactoryTests
@end
Expand All @@ -40,6 +41,8 @@ - (void)setUp
_exceptionTestFactory = [[TyphoonBlockComponentFactory alloc] initWithAssembly:[ExceptionTestAssembly assembly]];
_circularDependenciesFactory = [[TyphoonBlockComponentFactory alloc] initWithAssembly:[CircularDependenciesAssembly assembly]];
_singletonsChainFactory = [[TyphoonBlockComponentFactory alloc] initWithAssembly:[SingletonsChainAssembly assembly]];
_infrastructureComponentsFactory = [[TyphoonBlockComponentFactory alloc] initWithAssembly:[InfrastructureComponentsAssembly assembly]];

}

- (void)test_resolves_component_using_selector
Expand Down
1 change: 1 addition & 0 deletions Tests/Factory/Shared/TyphoonSharedComponentFactoryTests.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
TyphoonComponentFactory* _exceptionTestFactory;
TyphoonComponentFactory* _circularDependenciesFactory;
TyphoonComponentFactory* _singletonsChainFactory;
TyphoonComponentFactory* _infrastructureComponentsFactory;
}

@end
14 changes: 14 additions & 0 deletions Tests/Factory/Shared/TyphoonSharedComponentFactoryTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,20 @@ - (void)test_resolves_property_values

}

#pragma mark - Infrastructure definitions

- (void)test_infratracture_mutator_component_recognized
{
NSArray *mutators = _infrastructureComponentsFactory.mutators;
assertThatInt([mutators count], equalToInt(1));
}

- (void)test_infratracture_componenents_filtered_out
{
assertThatInt([[_infrastructureComponentsFactory registry] count], equalToInt(1));
}


/* ====================================================================================================================================== */
#pragma mark - Circular dependencies.

Expand Down
2 changes: 2 additions & 0 deletions Tests/Factory/Xml/TyphoonXmlComponentFactoryTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ - (void)setUp
_exceptionTestFactory = [[TyphoonXmlComponentFactory alloc] initWithConfigFileName:@"ExceptionTestAssembly.xml"];
_circularDependenciesFactory = [[TyphoonXmlComponentFactory alloc] initWithConfigFileName:@"CircularDependenciesAssembly.xml"];
_singletonsChainFactory = [[TyphoonXmlComponentFactory alloc] initWithConfigFileName:@"SingletonsChainAssembly.xml"];
_infrastructureComponentsFactory = [[TyphoonXmlComponentFactory alloc] initWithConfigFileName:@"InfratructureComponentsAssembly.xml"];

}

- (void)test_injects_initializer_by_value
Expand Down
Loading

0 comments on commit 201b25d

Please sign in to comment.