/*! @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