/*!
@header FTOrderedEdgeSet
@abstract Module of FT
@availability OS X, GNUstep
@copyright 2004, 2005, 2006 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-------------------------------------------------------------------------
Modification history
07.08.05 ola initial version
23.08.06 ola license changed
-------------------------------------------------------------------------
*/
#include
#include
#include
#include
@implementation FTOrderedEdgeSetImpl
- init {
self = [super init];
self->edges = [[NSMutableArray alloc] init];
self->sourceNodeIdToArrayOfEdgeIndexes = [[NSMutableDictionary alloc] init];
self->targetNodeIdToArrayOfEdgeIndexes = [[NSMutableDictionary alloc] init];
self->edgeIdToEdgeIndex = [[NSMutableDictionary alloc] init];
self = [self initTransientFields];
return self;
}
- initTransientFields {
self->lock = [[NSLock alloc] init];
return self;
}
- (id) initWithCoder:(NSCoder *) decoder {
self = [self initTransientFields];
self->edges = [[decoder decodeObject] retain];
self->sourceNodeIdToArrayOfEdgeIndexes = [[decoder decodeObject] retain];
self->targetNodeIdToArrayOfEdgeIndexes = [[decoder decodeObject] retain];
self->edgeIdToEdgeIndex = [[decoder decodeObject] retain];
return self;
}
- (void) dealloc {
[self->edges release];
[self->sourceNodeIdToArrayOfEdgeIndexes release];
[self->targetNodeIdToArrayOfEdgeIndexes release];
[self->edgeIdToEdgeIndex release];
[self->lock release];
[super dealloc];
}
- addIdOfNode: (id ) aNode
ofEdgeArrayIndex: (NSNumber *) anEdgeArrayIndex
toNodeIdToArrayMap: (NSMutableDictionary *) dict {
NSMutableArray *edgeArray;
/**
* fetch array of edges for given node id. If not existent then create one:
*/
edgeArray = (NSMutableArray *) [dict objectForKey: [aNode nodeId]];
if( nil == edgeArray ) {
edgeArray = [[NSMutableArray alloc] init];
[dict setObject: edgeArray forKey: [aNode nodeId]];
} else {
[edgeArray retain];
}
[edgeArray addObject: anEdgeArrayIndex ];
return self;
}
- appendEdge: (FTEdgeImpl *) toAdd {
NSNumber *index = nil;
if( nil == toAdd ) {
[[[ECIllegalArgumentException alloc]
initWithArgumentInfo: @"FTOrderedEdgeSet::appendEdge: "\
"nil for edge specified"] raise];
}
if( nil == [toAdd edgeId] ) {
[[[ECIllegalArgumentException alloc]
initWithArgumentInfo: @"FTOrderedEdgeSet::appendEdge: "\
"nil for edge specified"] raise];
}
if( nil != [self->edgeIdToEdgeIndex objectForKey: [toAdd edgeId]] ) {
/* TODO: This test has to be done at a central instance in order to check that
* edge identifiers are globally unique!
*/
[self->lock unlock];
[[[ECIllegalArgumentException alloc]
initWithArgumentInfo: @"FTOrderedEdgeSet::appendEdge: Edge with the "\
"specified id already exists!"] raise];
}
index = [[NSNumber alloc] initWithUnsignedInt: [self->edges count]];
[self->edges addObject: toAdd];
[self->edgeIdToEdgeIndex setObject: index forKey: [toAdd edgeId]];
[self addIdOfNode: [toAdd sourceNode]
ofEdgeArrayIndex: index
toNodeIdToArrayMap: self->sourceNodeIdToArrayOfEdgeIndexes
];
[self addIdOfNode: [toAdd targetNode]
ofEdgeArrayIndex: index
toNodeIdToArrayMap: self->targetNodeIdToArrayOfEdgeIndexes
];
return self;
}
- (ft_edge_type_t) edgeType: (id ) toLookFor {
ft_edge_type_t to_return = FT_EDGE_NOT_IN_SET;
if( nil != [self->edgeIdToEdgeIndex objectForKey: [toLookFor edgeId]] ) {
if( nil != [self->sourceNodeIdToArrayOfEdgeIndexes
objectForKey: [[toLookFor sourceNode] nodeId]] ) {
to_return = FT_EDGE_IS_INCOMING;
} else {
if( nil != [self->targetNodeIdToArrayOfEdgeIndexes
objectForKey: [[toLookFor targetNode] nodeId]] ) {
to_return = FT_EDGE_IS_OUTGOING;
} else {
[[[ECIllegalStateException alloc]
initWithIllegalStateInfo: @"FTOrderedEdgeSetImpl::edgeType: got an "\
"edge whose nodes are neither in source nor in target node id set!"]
raise];
}
}
}
return to_return;
}
- (id ) edgesWithNodeId: (id ) aNodeId
inNodeIdToArrayOfEdges: (NSDictionary *) map {
NSArray *edgeIndexArray;
NSMutableArray *edgeArray;
[self->lock lock];
edgeIndexArray = [map objectForKey: aNodeId];
edgeArray = [[NSMutableArray alloc] init];
if( nil != edgeArray ) {
/**
* Got an array of indexes within edge array. Now fetch the corresponding
* edges
*/
int i;
for( i = 0; i < [edgeIndexArray count]; i++ ) {
NSNumber *index = [edgeIndexArray objectAtIndex: i];
[edgeArray addObject: [self->edges objectAtIndex: [index intValue]]];
}
}
[self->lock unlock];
return [[ECArrayIterator alloc] initWithArray: edgeArray];
}
- (id ) edgesWithSourceNodeId: (id ) aNodeId {
return [self edgesWithNodeId: aNodeId
inNodeIdToArrayOfEdges: self->sourceNodeIdToArrayOfEdgeIndexes];
}
- (id ) edgesWithTargetNodeId: (id ) aNodeId {
return [self edgesWithNodeId: aNodeId
inNodeIdToArrayOfEdges: self->targetNodeIdToArrayOfEdgeIndexes];
}
- (void) encodeWithCoder: (NSCoder *) encoder {
[encoder encodeObject: self->edges];
[encoder encodeObject: self->sourceNodeIdToArrayOfEdgeIndexes];
[encoder encodeObject: self->targetNodeIdToArrayOfEdgeIndexes];
[encoder encodeObject: self->edgeIdToEdgeIndex];
}
- removeEdge: (id ) toRemove {
//__FTNodeIdToEdgeArrayIndex *edgeInfo;
[self->lock lock];
if( nil == [self->edgeIdToEdgeIndex objectForKey: [toRemove edgeId]] ) {
[self->lock unlock];
return self;
}
#if 0
/**
* search incoming links:
*/
edgeInfo = [[__FTNodeIdToEdgeArrayIndex alloc]
initWithNodeId: [[toRemove sourceNode] nodeId]
withNodeIdToArrayEdgesDictionary: self->sourceNodeIdToArrayOfEdgeIndexes
withEdge: toRemove
withEdgeArray: self->edges];
if( [edgeInfo withinAnEdge] ) {
NSArray *indexArray = [edgeInfo indexArray];
int i;
for( i = 0; i < [indexArray count]; TODO --> muss mutable sein!!
[[edgeInfo array] removeObjectAtIndex: [edgeInfo arrayIndex]];
}
[edgeInfo release];
/**
* search outgoing links:
*/
edgeInfo = [[__FTNodeIdToEdgeArrayIndex alloc]
initWithNodeId: [[toRemove targetNode] nodeId]
withNodeIdToArrayEdgesDictionary: self->targetNodeIdToArrayOfEdgeIndexes
withEdge: toRemove
withEdgeArray: self->edges];
if( [edgeInfo withinAnEdge] ) {
[[edgeInfo array] removeObjectAtIndex: [edgeInfo arrayIndex]];
}
[edgeInfo release];
[self->edgeIdToEdgeIndex removeObjectForKey: [toRemove edgeId]];
#endif
[self->lock unlock];
return self;
}
- removeEdges: (id ) toRemove {
id edge;
while( [toRemove hasNext] ) {
edge = [toRemove next];
[self removeEdge: edge];
}
return self;
}
@end
@implementation __FTOrderedEdgeSetFilter
- initWithsourceNodeIdToArrayOfEdgeIndexes:
(NSMutableDictionary *) asourceNodeIdToArrayOfEdgeIndexes
targetNodeIdToArrayOfEdgeIndexes:
(NSMutableDictionary *) atargetNodeIdToArrayOfEdgeIndexes
edgeIdToEdgeIndex: (NSMutableDictionary *) anedgeIdToEdgeIndex {
self = [super init];
self->sourceNodeIdToArrayOfEdgeIndexes = [asourceNodeIdToArrayOfEdgeIndexes retain];
self->targetNodeIdToArrayOfEdgeIndexes = [atargetNodeIdToArrayOfEdgeIndexes retain];
self->edgeIdToEdgeIndex = [anedgeIdToEdgeIndex retain];
self->filterSourceNodeId = nil;
self->filterTargetNodeId = nil;
self->filterEdge = nil;
self->filteredEdgeIndexes = nil;
self->filtered = NO;
return self;
}
- (void) dealloc {
[self->sourceNodeIdToArrayOfEdgeIndexes release];
[self->targetNodeIdToArrayOfEdgeIndexes release];
[self->edgeIdToEdgeIndex release];
if( nil != self->filteredEdgeIndexes ) {
[self->filteredEdgeIndexes release];
}
if( nil != self->filterSourceNodeId ) {
[self->filterSourceNodeId release];
}
if( nil != self->filterTargetNodeId ) {
[self->filterTargetNodeId release];
}
if( nil != self->filterEdge ) {
[self->filterEdge release];
}
[super dealloc];
}
- setFilterSourceNodeId: (id ) aNodeId {
self->filterSourceNodeId = [aNodeId retain];
return self;
}
- setFilterTargetNodeId: (id ) aNodeId {
self->filterTargetNodeId = [aNodeId retain];
return self;
}
- setFilterEdge: (id ) anEdge {
[self->filterEdge retain];
return self;
}
- filterNodeId: (id ) aNodeId
nodeIdToArrayOfEdgeIndexes: (NSDictionary *) nodeIdToArrayOfEdgeIndexes
filteredEdgeIndexes: (NSMutableArray *) filteredEdges {
NSArray *edgeIndexes = [nodeIdToArrayOfEdgeIndexes objectForKey: aNodeId];
if( nil != edgeIndexes ) {
[filteredEdges addObjectsFromArray: edgeIndexes];
}
return self;
}
- filter {
NSNumber *edgeIndex;
if( nil != self->filteredEdgeIndexes ) {
return self;
}
self->filteredEdgeIndexes = [[NSMutableArray alloc] init];
/**
* determine corresponding arrays of sourceNodeIdToArrayOfEdgeIndexes and
* sourceNodeIdToArrayOfEdgeIndexes and filter out all entries which do not
* point to an edge which is equal to the specified filterEdge. Do not filter
* out any entry if no filterEdge is being given.
*/
if( nil != self->sourceNodeIdToArrayOfEdgeIndexes ) {
[self filterNodeId: self->filterSourceNodeId
nodeIdToArrayOfEdgeIndexes: self->sourceNodeIdToArrayOfEdgeIndexes
filteredEdgeIndexes: self->filteredEdgeIndexes];
}
if( nil != self->targetNodeIdToArrayOfEdgeIndexes ) {
[self filterNodeId: self->filterTargetNodeId
nodeIdToArrayOfEdgeIndexes: self->targetNodeIdToArrayOfEdgeIndexes
filteredEdgeIndexes: self->filteredEdgeIndexes];
}
edgeIndex = [self->edgeIdToEdgeIndex objectForKey: [filterEdge edgeId]];
if( nil != edgeIndex ) {
[self->filteredEdgeIndexes addObject: edgeIndex];
}
return self;
}
@end