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

  <pre>
  -------------------------------------------------------------------------
  Modification history

  07.08.05 ola     initial version
  23.08.06 ola     license changed
  -------------------------------------------------------------------------
  </pre>
*/

#if !defined(__FTOrderedEdgeSetImpl_H)
#define __FTOrderedEdgeSetImpl_H

#include <Foundation/Foundation.h>
#include <FT/FTObject.h>
#include <FT/FTEdgeImpl.h>
#include <FT/FTOrderedEdgeSet.h>


@class __FTNodeIdToEdgeArrayIndex;


/*!
 * @class FTOrderedEdgeSetImpl
 * @abstract This classes stores a set of FTEdgeImpl instances.
 * @discussion The edges are stored in the order they are added to the set.
 *   Modifications to the set, like e.g. the deletion of an edge, directly
 *   have an impact on the order
 */
@interface FTOrderedEdgeSetImpl : FTObject <NSCoding, FTOrderedEdgeSet> {
  @private
    NSMutableArray *edges;
    
    /**
     * maps a node id to an array where each entry is of type NSNumber 
     * representing an index related to "edges"
     */
    NSMutableDictionary *sourceNodeIdToArrayOfEdgeIndexes;
    /**
     * maps a node id to an array where each entry is of type NSNumber 
     * representing an index related to "edges"
     */
    NSMutableDictionary *targetNodeIdToArrayOfEdgeIndexes;
    
    /**
     * maps an edge id to an array where each entry is of type NSNumber 
     * representing an index related to "edges"
     */
    NSMutableDictionary *edgeIdToEdgeIndex;
    
    NSLock *lock;
}

- init;


/*!
 * @method initTransientFields
 * @abstract Initialize all transient fields of the receiver
 * @result self
 */
- initTransientFields;


/*!
 * @method initWithCode
 * @abstract initializer called by deserialization process
 * @param decoder to use
 * @result self
 */
- (id) initWithCoder:(NSCoder *) decoder;


- (void) dealloc;


/*!
 * @method addIdOfNode
 * @abstract internal helper node used to add an entry to either
 * incomingNodeIdToArrayOfEdges or outgoingNodeIdToArrayEdges
 * @param aNode node to read the identifier from
 * @param anEdgeArrayIndex index where the edge is stored
 * @param dict dictionary to update (incomingNodeIdToArrayOfEdges or 
 *   outgoingNodeIdToArrayEdges)
 */
- addIdOfNode: (id <FTNode>) aNode 
  ofEdgeArrayIndex: (NSNumber *) anEdgeArrayIndex
  toNodeIdToArrayMap: (NSMutableDictionary *) dict;
  
  
/*!
 * @method appendEdge
 * @abstract appends an edge to the set of edges.
 * @param toAdd edge to add. Its edge identifier must be unique.
 * @throws ECIllegalArgumentException if edge identifier is not unique
 * @result index of array where the edge has been added to
 */
- appendEdge: (FTEdgeImpl *) toAdd;


/*!
 * @method edgeType
 * @abstract Checks whether a given node is with the set and if so, it 
 * determines the type of this node (incoming or outgoing)
 * @result FT_EDGE_NOT_IN_SET, FT_EDGE_IS_INCOMING or FT_EDGE_IS_OUTGOING
 */
- (ft_edge_type_t) edgeType: (id <FTEdge>) toLookFor;


/*!
 * @method edgesWithSourceNodeId
 * @abstract all edges having the specified node as source node
 * @result iterator of all edges having the specified node as source node
 */
- (id <ECIterator>) edgesWithSourceNodeId: (id <FTId>) aNodeId;


/*!
 * @method edgesWithTargetNodeId
 * @abstract all edges having the specified node as target node
 * @result iterator of all edges having the specified node as target node
 */

- (id <ECIterator>) edgesWithTargetNodeId: (id <FTId>) aNodeId;


/*!
 * @method encodeWithCoder
 * @abstract Is being called in order to serialize this instance
 * @param encoder object to be used for serialization
 */
- (void) encodeWithCoder: (NSCoder *) encoder;


/*!
 * @method removeEdge
 * @abstract Removes the given ot from the set.
 * @result self
 */
- removeEdge: (id <FTEdge>) toRemove;


/*!
 * @method removeEdges
 * @abstract Searches the given iterator and removes all nodes which are to 
 * be found in this set. Ignores all edges not to be found in this set.
 * @param toRemove iteration of edges to be removed
 * @result self
 */
- removeEdges: (id <ECIterator>) toRemove;
@end


/*!
 * @class __FTOrderedEdgeSetFilter
 * @abstract Used to filter edges based on their identifiers or the related
 *   nodes.
 */
@interface __FTOrderedEdgeSetFilter : FTObject {
  @private
  
  NSMutableArray *filteredEdgeIndexes;
  
  NSMutableDictionary *sourceNodeIdToArrayOfEdgeIndexes;
  NSMutableDictionary *targetNodeIdToArrayOfEdgeIndexes;
  NSMutableDictionary *edgeIdToEdgeIndex;
  
  id <FTId> filterSourceNodeId;
  id <FTId> filterTargetNodeId;
  id <FTEdge> filterEdge;

  NSMutableArray *filteredSourceNodeToEdgeSet;
  NSMutableArray *filteredTargetNodeToEdgeSet;
  
  BOOL filtered;
}


/*!
 * @method initWithsourceNodeIdToArrayOfEdgeIndexes
 * @param asourceNodeIdToArrayOfEdgeIndexes related array of 
 *   FTOrderedEdgeSetImpl
  * @param atargetNodeIdToArrayOfEdgeIndexes related array of 
 *   FTOrderedEdgeSetImpl
 *  @param anedgeIdToEdgeIndex related array of FTOrderedEdgeSetImpl
 * @result self
 */
- initWithsourceNodeIdToArrayOfEdgeIndexes: 
    (NSMutableDictionary *) asourceNodeIdToArrayOfEdgeIndexes
    targetNodeIdToArrayOfEdgeIndexes: 
      (NSMutableDictionary *) atargetNodeIdToArrayOfEdgeIndexes
    edgeIdToEdgeIndex: (NSMutableDictionary *) anedgeIdToEdgeIndex;
    
- (void) dealloc;



- setFilterSourceNodeId: (id <FTId>) aNodeId;
- setFilterTargetNodeId: (id <FTId>) aNodeId;
- setFilterEdge: (id <FTId>) anEdge;

@end

#endif
