main
  1//
  2// Licensed under the terms in License.txt
  3//
  4// Copyright 2010 Allen Ding. All rights reserved.
  5//
  6
  7#import "KWContextNode.h"
  8#import "KWExampleNodeVisitor.h"
  9#import "KWExample.h"
 10#import "KWFailure.h"
 11
 12@implementation KWContextNode
 13
 14@synthesize parentContext;
 15
 16#pragma mark -
 17#pragma mark Initializing
 18
 19- (id)initWithCallSite:(KWCallSite *)aCallSite parentContext:(KWContextNode *)node description:(NSString *)aDescription
 20{
 21    if ((self = [super init])) {
 22        parentContext = [node retain];
 23        callSite = [aCallSite retain];
 24        description = [aDescription copy];
 25        nodes = [[NSMutableArray alloc] init];
 26        performedExampleCount = 0;
 27    }
 28
 29    return self;
 30}
 31
 32+ (id)contextNodeWithCallSite:(KWCallSite *)aCallSite parentContext:(KWContextNode *)contextNode description:(NSString *)aDescription {
 33    return [[[self alloc] initWithCallSite:aCallSite parentContext:contextNode description:aDescription] autorelease];
 34}
 35
 36- (void)dealloc {
 37    [parentContext release];
 38    [callSite release];
 39    [description release];
 40    [registerMatchersNode release];
 41    [beforeAllNode release];
 42    [afterAllNode release];
 43    [beforeEachNode release];
 44    [afterEachNode release];
 45    [nodes release];
 46    [super dealloc];
 47}
 48
 49#pragma mark -
 50#pragma mark  Getting Call Sites
 51
 52@synthesize callSite;
 53
 54#pragma mark -
 55#pragma mark Getting Descriptions
 56
 57@synthesize description;
 58
 59#pragma mark -
 60#pragma mark Managing Nodes
 61
 62@synthesize registerMatchersNode;
 63@synthesize beforeAllNode;
 64@synthesize afterAllNode;
 65@synthesize beforeEachNode;
 66@synthesize afterEachNode;
 67@synthesize nodes;
 68
 69- (void)addContextNode:(KWContextNode *)aNode {
 70    [(NSMutableArray *)self.nodes addObject:aNode];
 71}
 72
 73- (void)setRegisterMatchersNode:(KWRegisterMatchersNode *)aNode {
 74    if (self.registerMatchersNode != nil)
 75        [NSException raise:@"KWContextNodeException" format:@"a register matchers node already exists"];
 76
 77    registerMatchersNode = [aNode retain];
 78}
 79
 80- (void)setBeforeEachNode:(KWBeforeEachNode *)aNode {
 81    if (self.beforeEachNode != nil)
 82        [NSException raise:@"KWContextNodeException" format:@"a before each node already exists"];
 83
 84    beforeEachNode = [aNode retain];
 85}
 86
 87- (void)setAfterEachNode:(KWAfterEachNode *)aNode {
 88    if (self.afterEachNode != nil)
 89        [NSException raise:@"KWContextNodeException" format:@"an after each node already exists"];
 90
 91    afterEachNode = [aNode retain];
 92}
 93
 94- (void)addItNode:(KWItNode *)aNode {
 95    [(NSMutableArray *)self.nodes addObject:aNode];
 96}
 97
 98- (void)addPendingNode:(KWPendingNode *)aNode {
 99    [(NSMutableArray *)self.nodes addObject:aNode];
100}
101
102- (void)performExample:(KWExample *)example withBlock:(void (^)(void))exampleBlock
103{
104    void (^innerExampleBlock)(void) = [exampleBlock copy];
105    
106    void (^outerExampleBlock)(void) = ^{
107        @try {
108            [self.registerMatchersNode acceptExampleNodeVisitor:example];
109            
110            if (performedExampleCount == 0) {
111                [self.beforeAllNode acceptExampleNodeVisitor:example];
112            }
113            
114            [self.beforeEachNode acceptExampleNodeVisitor:example];
115            
116            innerExampleBlock();
117            
118            [self.afterEachNode acceptExampleNodeVisitor:example];
119
120            if ([example isLastInContext:self]) {
121                [self.afterAllNode acceptExampleNodeVisitor:example];
122            }
123            
124        } @catch (NSException *exception) {
125            KWFailure *failure = [KWFailure failureWithCallSite:self.callSite format:@"%@ \"%@\" raised", [exception name], [exception reason]];
126            [example reportFailure:failure];
127        }
128        
129        performedExampleCount++;
130    };
131    if (parentContext == nil) {
132        outerExampleBlock();
133    }
134    else {
135        [parentContext performExample:example withBlock:outerExampleBlock];
136    }
137    [innerExampleBlock release];
138}
139
140#pragma mark -
141#pragma mark Accepting Visitors
142
143- (void)acceptExampleNodeVisitor:(id<KWExampleNodeVisitor>)aVisitor {
144    [aVisitor visitContextNode:self];
145}
146
147@end