#import "TreeNode.h"
#define STRIP(X) [X stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
@implementation
TreeNode
@synthesize
parent;
@synthesize
children;
@synthesize
key;
@synthesize
leafvalue;
#pragma mark Create and Initialize TreeNodes
- (TreeNode *) init
{
if
(
self
= [
super
init])
{
self
.key =
nil
;
self
.leafvalue =
nil
;
self
.parent =
nil
;
self
.children =
nil
;
}
return
self
;
}
+ (TreeNode *) treeNode
{
return
[[[
self
alloc] init] autorelease];
}
#pragma mark TreeNode type routines
- (
BOOL
) isLeaf
{
return
(
self
.children.count == 0);
}
- (
BOOL
) hasLeafValue
{
return
(
self
.leafvalue !=
nil
);
}
#pragma mark TreeNode data recovery routines
- (
NSArray
*) keys
{
NSMutableArray
*results = [
NSMutableArray
array];
for
(TreeNode *node in
self
.children) [results addObject:node.key];
return
results;
}
- (
NSArray
*) allKeys
{
NSMutableArray
*results = [
NSMutableArray
array];
for
(TreeNode *node in
self
.children)
{
[results addObject:node.key];
[results addObjectsFromArray:node.allKeys];
}
return
results;
}
- (
NSArray
*) uniqArray: (
NSArray
*) anArray
{
NSMutableArray
*array = [
NSMutableArray
array];
for
(
id
object in [anArray sortedArrayUsingSelector:
@selector
(caseInsensitiveCompare:)])
if
(![[array lastObject] isEqualToString:object]) [array addObject:object];
return
array;
}
- (
NSArray
*) uniqKeys
{
return
[
self
uniqArray:[
self
keys]];
}
- (
NSArray
*) uniqAllKeys
{
return
[
self
uniqArray:[
self
allKeys]];
}
- (
NSArray
*) leaves
{
NSMutableArray
*results = [
NSMutableArray
array];
for
(TreeNode *node in
self
.children)
if
(node.leafvalue) [results addObject:node.leafvalue];
return
results;
}
- (
NSArray
*) allLeaves
{
NSMutableArray
*results = [
NSMutableArray
array];
for
(TreeNode *node in
self
.children)
{
if
(node.leafvalue) [results addObject:node.leafvalue];
[results addObjectsFromArray:node.allLeaves];
}
return
results;
}
#pragma mark TreeNode search and retrieve routines
- (TreeNode *) objectForKey: (
NSString
*) aKey
{
TreeNode *result =
nil
;
for
(TreeNode *node in
self
.children)
if
([node.key isEqualToString: aKey])
{
result = node;
break
;
}
if
(result)
return
result;
for
(TreeNode *node in
self
.children)
{
result = [node objectForKey:aKey];
if
(result)
break
;
}
return
result;
}
- (
NSString
*) leafForKey: (
NSString
*) aKey
{
TreeNode *node = [
self
objectForKey:aKey];
return
node.leafvalue;
}
- (
NSMutableArray
*) objectsForKey: (
NSString
*) aKey
{
NSMutableArray
*result = [
NSMutableArray
array];
for
(TreeNode *node in
self
.children)
{
if
([node.key isEqualToString: aKey]) [result addObject:node];
[result addObjectsFromArray:[node objectsForKey:aKey]];
}
return
result;
}
- (
NSMutableArray
*) leavesForKey: (
NSString
*) aKey
{
NSMutableArray
*result = [
NSMutableArray
array];
for
(TreeNode *node in [
self
objectsForKey:aKey])
if
(node.leafvalue)
[result addObject:node.leafvalue];
return
result;
}
- (TreeNode *) objectForKeys: (
NSArray
*) keys
{
if
([keys count] == 0)
return
self
;
NSMutableArray
*nextArray = [
NSMutableArray
arrayWithArray:keys];
[nextArray removeObjectAtIndex:0];
for
(TreeNode *node in
self
.children)
{
if
([node.key isEqualToString:[keys objectAtIndex:0]])
return
[node objectForKeys:nextArray];
}
return
nil
;
}
- (
NSString
*) leafForKeys: (
NSArray
*) keys
{
TreeNode *node = [
self
objectForKeys:keys];
return
node.leafvalue;
}
#pragma mark output utilities
- (
void
) dumpAtIndent: (
int
) indent into:(
NSMutableString
*) outstring
{
for
(
int
i = 0; i < indent; i++) [outstring appendString:@
"--"
];
[outstring appendFormat:@
"[%2d] Key: %@ "
, indent, key];
if
(
self
.leafvalue) [outstring appendFormat:@
"(%@)"
, STRIP(
self
.leafvalue)];
[outstring appendString:@
"\n"
];
for
(TreeNode *node in
self
.children) [node dumpAtIndent:indent + 1 into: outstring];
}
- (
NSString
*) dump
{
NSMutableString
*outstring = [[
NSMutableString
alloc] init];
[
self
dumpAtIndent:0 into:outstring];
return
[outstring autorelease];
}
#pragma mark conversion utilities
- (
NSMutableDictionary
*) dictionaryForChildren
{
NSMutableDictionary
*results = [
NSMutableDictionary
dictionary];
for
(TreeNode *node in
self
.children)
if
(node.hasLeafValue) [results setObject:node.leafvalue forKey:node.key];
return
results;
}
#pragma mark invocation forwarding
- (
id
)forwardingTargetForSelector:(
SEL
)sel
{
if
([
self
.children respondsToSelector:sel])
return
self
.children;
return
nil
;
}
- (
BOOL
)respondsToSelector:(
SEL
)aSelector
{
if
( [
super
respondsToSelector:aSelector] )
return
YES
;
if
([
self
.children respondsToSelector:aSelector])
return
YES
;
return
NO
;
}
- (
BOOL
)isKindOfClass:(Class)aClass
{
if
(aClass == [TreeNode
class
])
return
YES
;
if
([
super
isKindOfClass:aClass])
return
YES
;
if
([
self
.children isKindOfClass:aClass])
return
YES
;
return
NO
;
}
#pragma mark cleanup
- (
void
) teardown
{
for
(TreeNode *node in [[
self
.children
copy
] autorelease]) [node teardown];
[
self
.parent.children removeObject:
self
];
self
.parent =
nil
;
}
- (
void
) dealloc
{
self
.parent =
nil
;
self
.children =
nil
;
self
.key =
nil
;
self
.leafvalue =
nil
;
[
super
dealloc];
}
@end