//===========================================================================
//  @(#) $Name: arts++-1-1-a12 $
//  @(#) $Id: ArtsFileUtil.cc,v 1.2 2004/04/21 23:51:32 kkeys Exp $
//===========================================================================
//  Copyright Notice
//
//  By accessing this software, arts++, you are duly informed
//  of and agree to be bound by the conditions described below in this
//  notice:
//
//  This software product, arts++, is developed by Daniel W. McRobb, and
//  copyrighted(C) 1998 by the University of California, San Diego
//  (UCSD), with all rights reserved.  UCSD administers the CAIDA grant,
//  NCR-9711092, under which part of this code was developed.
//
//  There is no charge for arts++ software.  You can redistribute it
//  and/or modify it under the terms of the GNU Lesser General Public
//  License, Version 2.1, February 1999, which is incorporated by
//  reference herein.
//
//  arts++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
//  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use
//  of it will not infringe on any third party's intellectual
//  property rights.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with arts++.  Copies can also be obtained from:
//
//    http://www.gnu.org/copyleft/lesser.html
//
//  or by writing to:
//
//  Free Software Foundation, Inc.
//  59 Temple Place, Suite 330
//  Boston, MA 02111-1307
//  USA
//
//  Or contact:
//
//    info@caida.org
//===========================================================================

extern "C" {
#include "artslocal.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
}

#ifdef HAVE_FSTREAM
  #include <fstream>
#else
  #include <fstream.h>
#endif
#include <string>
#include <iterator>
#include <map>

#include "ArtsFileUtil.hh"
#include "ArtsDebug.hh"
#include "ArtsPackageVersion.hh"

using namespace std;

typedef map<ArtsAggregatorMapKey,time_t,less<ArtsAggregatorMapKey> >  \
IntervalStartMap_t;

extern char *tzname[2];
extern int   errno;

const string rcsid = "@(#) $Name: arts++-1-1-a12 $ $Id: ArtsFileUtil.cc,v 1.2 2004/04/21 23:51:32 kkeys Exp $";

static const ArtsPackageVersion  k_artsVersion = ArtsPackageVersion(rcsid);

//----------------------------------------------------------------------------
//                       ArtsFileUtil::ArtsFileUtil() 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsFileUtil::ArtsFileUtil()
{
  _numTopEntries = 0;
  
  #ifndef NDEBUG
    ++ArtsFileUtil::_numObjects;
  #endif
}

//----------------------------------------------------------------------------
//      ArtsFileUtil::ArtsFileUtil(const ArtsFileUtil & artsFileUtil) 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsFileUtil::ArtsFileUtil(const ArtsFileUtil & artsFileUtil)
{
  #ifndef NDEBUG
    ++ArtsFileUtil::_numObjects;
  #endif
}

//----------------------------------------------------------------------------
//                      ArtsFileUtil::~ArtsFileUtil() 
//............................................................................
//  
//----------------------------------------------------------------------------
ArtsFileUtil::~ArtsFileUtil()
{
  #ifndef NDEBUG
    --ArtsFileUtil::_numObjects;
  #endif
}

//----------------------------------------------------------------------------
//    void ArtsFileUtil::
//    FinishProtocolTableAgg(ArtsProtocolTableAggregatorMap & protoAggMap, 
//                           ofstream & out, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
FinishProtocolTableAgg(ArtsProtocolTableAggregatorMap & protoAggMap,
                       ofstream & out, bool quiet) const
{
  ArtsProtocolTableAggregatorMap::iterator  protoAggIter;
  ArtsProtocolTable  *protocolTable = (ArtsProtocolTable *)0;

  if ((protoAggMap).size() > 0) {
    for (protoAggIter = protoAggMap.begin();
         protoAggIter != protoAggMap.end(); ++protoAggIter) {
      protocolTable =
        ((*protoAggIter).second)->ConvertToArtsProtocolTable();
      protocolTable->write(out);
      delete(protocolTable);
      delete((*protoAggIter).second);
      if (!quiet) {
        cout << "+";
        cout.flush();
      }
    }
    protoAggMap.erase(protoAggMap.begin(),protoAggMap.end());
  }
  return;
}

//----------------------------------------------------------------------------
//        void ArtsFileUtil::
//        FinishTosTableAgg(ArtsTosTableAggregatorMap & tosAggMap, 
//                          ofstream & out, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
FinishTosTableAgg(ArtsTosTableAggregatorMap & tosAggMap,
                  ofstream & out, bool quiet) const
{
  ArtsTosTableAggregatorMap::iterator   tosAggIter;
  ArtsTosTable                         *tosTable = (ArtsTosTable *)0;

  if ((tosAggMap).size() > 0) {
    for (tosAggIter = tosAggMap.begin();
         tosAggIter != tosAggMap.end(); ++tosAggIter) {
      tosTable =
        ((*tosAggIter).second)->ConvertToArtsTosTable();
      tosTable->write(out);
      delete(tosTable);
      delete((*tosAggIter).second);
      if (!quiet) {
        cout << "+";
        cout.flush();
      }
    }
    tosAggMap.erase(tosAggMap.begin(),tosAggMap.end());
  }
  return;
}

//----------------------------------------------------------------------------
// void ArtsFileUtil::
// FinishInterfaceMatrixAgg(ArtsInterfaceMatrixAggregatorMap & intfmAggMap, 
//                                   ofstream & out, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
FinishInterfaceMatrixAgg(ArtsInterfaceMatrixAggregatorMap & intfmAggMap,
                         ofstream & out, bool quiet) const
{
  ArtsInterfaceMatrixAggregatorMap::iterator    intfmAggIter;
  ArtsInterfaceMatrix       *intfMatrix = (ArtsInterfaceMatrix *)NULL;

  if (intfmAggMap.size() > 0) {
    for (intfmAggIter = intfmAggMap.begin();
         intfmAggIter != intfmAggMap.end(); ++intfmAggIter) {
      intfMatrix = ((*intfmAggIter).second)->ConvertToArtsInterfaceMatrix();
      intfMatrix->write(out);
      delete(intfMatrix);
      delete((*intfmAggIter).second);
      if (!quiet) {
        cout << "+";
        cout.flush();
      }
    }
    intfmAggMap.erase(intfmAggMap.begin(),intfmAggMap.end());
  }
  return;
}

//----------------------------------------------------------------------------
//   void ArtsFileUtil::
//   FinishNextHopTableAgg(ArtsNextHopTableAggregatorMap & nextHopAggMap, 
//                         ofstream & out, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
FinishNextHopTableAgg(ArtsNextHopTableAggregatorMap & nextHopAggMap,
                      ofstream & out, bool quiet) const
{
  ArtsNextHopTableAggregatorMap::iterator   nextHopAggIter;
  ArtsNextHopTable  *nextHopTable = (ArtsNextHopTable *)NULL;

  if (nextHopAggMap.size() > 0) {
    for (nextHopAggIter = nextHopAggMap.begin();
         nextHopAggIter != nextHopAggMap.end(); ++nextHopAggIter) {
      nextHopTable =
        ((*nextHopAggIter).second)->ConvertToArtsNextHopTable();
      nextHopTable->write(out);
      delete(nextHopTable);
      delete((*nextHopAggIter).second);
      if (!quiet) {
        cout << "+";
        cout.flush();
      }
    }
    nextHopAggMap.erase(nextHopAggMap.begin(),nextHopAggMap.end());
  }
  return;
}

//----------------------------------------------------------------------------
//        void 
//        FinishAsMatrixAgg(ArtsAsMatrixAggregatorMap & asmAggMap, 
//                          ofstream & out, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
FinishAsMatrixAgg(ArtsAsMatrixAggregatorMap & asmAggMap,
                  ofstream & out, bool quiet) const
{
  ArtsAsMatrixAggregatorMap::iterator     asmAggIter;
  ArtsAsMatrix                           *asMatrix = (ArtsAsMatrix *)NULL;
  
  if (asmAggMap.size() > 0) {
    for (asmAggIter = asmAggMap.begin();
         asmAggIter != asmAggMap.end(); ++asmAggIter) {
      asMatrix = ((*asmAggIter).second)->ConvertToArtsAsMatrix();
      asMatrix->write(out);
      delete(asMatrix);
      delete((*asmAggIter).second);
      if (!quiet) {
        cout << "+";
        cout.flush();
      }
    }
    asmAggMap.erase(asmAggMap.begin(),asmAggMap.end());
    
  }
  return;
}

//----------------------------------------------------------------------------
//      void ArtsFileUtil::
//      FinishNetMatrixAgg(ArtsNetMatrixAggregatorMap & netmAggMap, 
//                         ofstream & out, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
FinishNetMatrixAgg(ArtsNetMatrixAggregatorMap & netmAggMap,
                   ofstream & out, bool quiet) const
{
  ArtsNetMatrixAggregatorMap::iterator    netmAggIter;
  ArtsNetMatrix                          *netMatrix = (ArtsNetMatrix *)NULL;

  if (netmAggMap.size() > 0) {
    for (netmAggIter = netmAggMap.begin();
         netmAggIter != netmAggMap.end(); ++netmAggIter) {
      netMatrix = ((*netmAggIter).second)->ConvertToArtsNetMatrix();
      netMatrix->write(out);
      delete(netMatrix);
      delete((*netmAggIter).second);
      if (!quiet) {
        cout << "+";
        cout.flush();
      }
    }

    netmAggMap.erase(netmAggMap.begin(),netmAggMap.end());
  }
  return;
}

//----------------------------------------------------------------------------
//      void ArtsFileUtil::
//      FinishPortMatrixAgg(ArtsPortMatrixAggregatorMap & portmAggMap, 
//                          ofstream & out, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
FinishPortMatrixAgg(ArtsPortMatrixAggregatorMap & portmAggMap,
                    ofstream & out, bool quiet) const
{
  ArtsPortMatrixAggregatorMap::iterator   portmAggIter;
  ArtsPortMatrix *portMatrix = (ArtsPortMatrix *)NULL;

  if (portmAggMap.size() > 0) {
    for (portmAggIter = portmAggMap.begin();
         portmAggIter != portmAggMap.end(); ++portmAggIter) {
      if (this->_portChooser.PortChoices().size() != 0) {
        ArtsSelectedPortTable *selPortTable =
          ((*portmAggIter).second)->ConvertToArtsSelectedPortTable(this->_portChooser);
        selPortTable->write(out);
        delete(selPortTable);
      }
      else {
        if (this->_numTopEntries > 0) {
          ArtsSelectedPortTable *selPortTable =
            ((*portmAggIter).second)->ConvertToArtsSelectedPortTable(this->_numTopEntries,false);
          selPortTable->write(out);
          delete(selPortTable);
        }
        else {
          ArtsPortMatrix *portMatrix =
            ((*portmAggIter).second)->ConvertToArtsPortMatrix();
          portMatrix->write(out);
          delete(portMatrix);
        }
      }
      
      delete((*portmAggIter).second);
      if (!quiet) {
        cout << "+";
        cout.flush();
      }
    }
    portmAggMap.erase(portmAggMap.begin(),portmAggMap.end());
  }
  return;
}

//----------------------------------------------------------------------------
//  void ArtsFileUtil::
//  AggregateProtocolTableData(ArtsProtocolTableAggregatorMap & protoAggMap,
//                             Arts * arts, ofstream & out,
//                             float hours, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
AggregateProtocolTableData(ArtsProtocolTableAggregatorMap & protoAggMap,
                           const Arts & arts, ofstream & out, float hours,
                           bool quiet) const
{
  vector<ArtsAttribute>::const_iterator       hostAttribute;
  vector<ArtsAttribute>::const_iterator       periodAttribute;
  vector<ArtsAttribute>::const_iterator       ifIndexAttribute;
  ArtsAggregatorMapKey                        protoKey;
  ArtsProtocolTableAggregatorMap::iterator    protoAggIter;
  static IntervalStartMap_t                   intervalStartMap;
  ArtsProtocolTable      *protocolTable = (ArtsProtocolTable *)NULL;
  
  protoAggMap.Add(arts);
  periodAttribute = arts.FindPeriodAttribute();

  hostAttribute = arts.FindHostAttribute();
  if (hostAttribute != arts.Attributes().end()) {
    protoKey.Router(hostAttribute->Host());
  }
  else {
    protoKey.Router(0);
  }

  ifIndexAttribute = arts.FindIfIndexAttribute();
  if (ifIndexAttribute != arts.Attributes().end()) {
    protoKey.IfIndex(ifIndexAttribute->IfIndex());
  }
  else {
    protoKey.IfIndex(0);
  }
  
  if (intervalStartMap.find(protoKey) == intervalStartMap.end()) {
    intervalStartMap[protoKey] = ((*periodAttribute).Period())[0];
  }

  if (hours > 0.0) {
    if ((periodAttribute->Period())[1] >
        (intervalStartMap[protoKey] + hours * 60 * 60)) {
      protoAggIter = protoAggMap.find(protoKey);
      if (protoAggIter != protoAggMap.end()) {
        protocolTable =
          ((*protoAggIter).second)->ConvertToArtsProtocolTable();
        protocolTable->write(out);
        delete(protocolTable);
        delete((*protoAggIter).second);
        if (!quiet) {
          cout << "+";
          cout.flush();
        }
        intervalStartMap.erase(intervalStartMap.find(protoKey));
        protoAggMap.erase(protoAggIter);
      }
    }
  }
  
  return;
}

//----------------------------------------------------------------------------
//        void ArtsFileUtil::
//        AggregateTosTableData(ArtsTosTableAggregatorMap & tosAggMap,
//                              const Arts & arts, ofstream & out,
//                              float hours, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
AggregateTosTableData(ArtsTosTableAggregatorMap & tosAggMap,
                      const Arts & arts, ofstream & out,
                      float hours, bool quiet) const
{
  vector<ArtsAttribute>::const_iterator     hostAttribute;
  vector<ArtsAttribute>::const_iterator     periodAttribute;
  vector<ArtsAttribute>::const_iterator     ifIndexAttribute;
  ArtsAggregatorMapKey                      tosKey;
  ArtsTosTableAggregatorMap::iterator       tosAggIter;
  static time_t                             intervalStart = 0;
  static IntervalStartMap_t                 intervalStartMap;
  
  tosAggMap.Add(arts);

  periodAttribute = arts.FindPeriodAttribute();

  hostAttribute = arts.FindHostAttribute();
  if (hostAttribute != arts.Attributes().end()) {
    tosKey.Router(hostAttribute->Host());
  }
  else {
    tosKey.Router(0);
  }

  ifIndexAttribute = arts.FindIfIndexAttribute();
  if (ifIndexAttribute != arts.Attributes().end()) {
    tosKey.IfIndex(ifIndexAttribute->IfIndex());
  }
  else {
    tosKey.IfIndex(0);
  }

  if (intervalStartMap.find(tosKey) == intervalStartMap.end()) {
    intervalStartMap[tosKey] = ((*periodAttribute).Period())[0];
  }

  if (hours > 0.0) {
    if ((periodAttribute->Period())[1] >
        (intervalStartMap[tosKey] + hours * 60 * 60)) {
      tosAggIter = tosAggMap.find(tosKey);
      if (tosAggIter != tosAggMap.end()) {
        ArtsTosTable *tosTable =
          ((*tosAggIter).second)->ConvertToArtsTosTable();
        tosTable->write(out);
        delete(tosTable);
        delete((*tosAggIter).second);
        if (!quiet) {
          cout << "+";
          cout.flush();
        }
        intervalStartMap.erase(intervalStartMap.find(tosKey));
        tosAggMap.erase(tosAggIter);
      }
    }
  }

  return;
}

//----------------------------------------------------------------------------
// void ArtsFileUtil::
// AggregateInterfaceMatrixData(ArtsInterfaceMatrixAggregatorMap & intfmAggMap,
//                              const Arts & arts, ofstream & out,
//                              float hours, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
AggregateInterfaceMatrixData(ArtsInterfaceMatrixAggregatorMap & intfmAggMap,
                             const Arts & arts, ofstream & out, float hours,
                             bool quiet) const
{
  vector<ArtsAttribute>::const_iterator       hostAttribute;
  vector<ArtsAttribute>::const_iterator       periodAttribute;
  vector<ArtsAttribute>::const_iterator       ifIndexAttribute;
  ArtsAggregatorMapKey                        intfmKey;
  ArtsInterfaceMatrixAggregatorMap::iterator  intfmAggIter;
  static IntervalStartMap_t                   intervalStartMap;

  intfmAggMap.Add(arts);

  hostAttribute = arts.FindHostAttribute();
  if (hostAttribute != arts.Attributes().end())
    intfmKey.Router(hostAttribute->Host());
  else
    intfmKey.Router(0);

  ifIndexAttribute = arts.FindIfIndexAttribute();
  if (ifIndexAttribute != arts.Attributes().end())
    intfmKey.IfIndex(ifIndexAttribute->IfIndex());
  else
    intfmKey.IfIndex(0);

  periodAttribute = arts.FindPeriodAttribute();
  if (intervalStartMap.find(intfmKey) == intervalStartMap.end())
    intervalStartMap[intfmKey] = ((*periodAttribute).Period())[0];

  if (hours > 0.0) {
    if ((periodAttribute->Period())[1] >
        (intervalStartMap[intfmKey] + hours * 60 * 60)) {
      intfmAggIter = intfmAggMap.find(intfmKey);
      if (intfmAggIter != intfmAggMap.end()) {
        ArtsInterfaceMatrix *intfMatrix =
          ((*intfmAggIter).second)->ConvertToArtsInterfaceMatrix();
        intfMatrix->write(out);
        delete(intfMatrix);
        delete((*intfmAggIter).second);
        if (!quiet) {
          cout << "+";
          cout.flush();
        }
        intervalStartMap.erase(intervalStartMap.find(intfmKey));
        intfmAggMap.erase(intfmAggIter);
      }
    }
  }

  return;
}

//----------------------------------------------------------------------------
//    void ArtsFileUtil::
//    AggregateNextHopTable(ArtsNextHopTableAggregatorMap & nextHopAggMap,
//                          const Arts & arts, ofstream & out, float hours, 
//                          bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
AggregateNextHopTable(ArtsNextHopTableAggregatorMap & nextHopAggMap,
                      const Arts & arts, ofstream & out, float hours,
                      bool quiet) const
{
  vector<ArtsAttribute>::const_iterator       hostAttribute;
  vector<ArtsAttribute>::const_iterator       periodAttribute;
  vector<ArtsAttribute>::const_iterator       ifIndexAttribute;
  ArtsAggregatorMapKey                        nextHopKey;
  ArtsNextHopTableAggregatorMap::iterator     nextHopAggIter;
  static IntervalStartMap_t                   intervalStartMap;

  nextHopAggMap.Add(arts);

  hostAttribute = arts.FindHostAttribute();
  if (hostAttribute != arts.Attributes().end())
    nextHopKey.Router(hostAttribute->Host());
  else
    nextHopKey.Router(0);
  
  ifIndexAttribute = arts.FindIfIndexAttribute();
  if (ifIndexAttribute != arts.Attributes().end())
    nextHopKey.IfIndex(ifIndexAttribute->IfIndex());
  else
    nextHopKey.IfIndex(0);

  periodAttribute = arts.FindPeriodAttribute();
  if (intervalStartMap.find(nextHopKey) == intervalStartMap.end())
    intervalStartMap[nextHopKey] = ((*periodAttribute).Period())[0];

  if (hours > 0.0) {
    if ((periodAttribute->Period())[1] >
        (intervalStartMap[nextHopKey] + hours * 60 * 60)) {
      nextHopAggIter = nextHopAggMap.find(nextHopKey);
      if (nextHopAggIter != nextHopAggMap.end()) {
        ArtsNextHopTable *nextHopTable =
          ((*nextHopAggIter).second)->ConvertToArtsNextHopTable();
        nextHopTable->write(out);
        delete(nextHopTable);
        delete((*nextHopAggIter).second);
        if (!quiet) {
          cout << "+";
          cout.flush();
        }
        intervalStartMap.erase(intervalStartMap.find(nextHopKey));
        nextHopAggMap.erase(nextHopAggIter);
      }
    }
  }
  return;
}

//----------------------------------------------------------------------------
//     void ArtsFileUtil::
//     AggregateAsMatrixData(ArtsAsMatrixAggregatorMap & asmAggMap,
//                           const Arts & arts, ofstream & out, float hours, 
//                           bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
AggregateAsMatrixData(ArtsAsMatrixAggregatorMap & asmAggMap,
                      const Arts & arts, ofstream & out, float hours,
                      bool quiet) const
{
  vector<ArtsAttribute>::const_iterator     hostAttribute;
  vector<ArtsAttribute>::const_iterator     periodAttribute;
  vector<ArtsAttribute>::const_iterator     ifIndexAttribute;
  ArtsAggregatorMapKey                      asmKey;
  ArtsAsMatrixAggregatorMap::iterator       asmAggIter;
  static IntervalStartMap_t                 intervalStartMap;
  
  //  Add the data to the aggregator map.
  asmAggMap.Add(arts);
  
  hostAttribute = arts.FindHostAttribute();
  if (hostAttribute != arts.Attributes().end())
    asmKey.Router(hostAttribute->Host());
  else
    asmKey.Router(0);
  
  ifIndexAttribute = arts.FindIfIndexAttribute();
  if (ifIndexAttribute != arts.Attributes().end())
    asmKey.IfIndex(ifIndexAttribute->IfIndex());
  else
    asmKey.IfIndex(0);

  periodAttribute = arts.FindPeriodAttribute();
  if (intervalStartMap.find(asmKey) == intervalStartMap.end())
    intervalStartMap[asmKey] = ((*periodAttribute).Period())[0];

  if (hours > 0.0) {
    if ((periodAttribute->Period())[1] >
        (intervalStartMap[asmKey] + hours * 60 * 60)) {
      asmAggIter = asmAggMap.find(asmKey);
      if (asmAggIter != asmAggMap.end()) {
        ArtsAsMatrix *asMatrix =
          ((*asmAggIter).second)->ConvertToArtsAsMatrix();
        asMatrix->write(out);
        delete(asMatrix);
        delete((*asmAggIter).second);
        if (!quiet) {
          cout << "+";
          cout.flush();
        }
        intervalStartMap.erase(intervalStartMap.find(asmKey));
        asmAggMap.erase(asmAggIter);
      }
    }
  }
  return;
}

//----------------------------------------------------------------------------
//      void ArtsFileUtil::
//      AggregateNetMatrixData(ArtsNetMatrixAggregatorMap & netmAggMap,
//                             const Arts & arts, ofstream & out, float hours, 
//                             bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
AggregateNetMatrixData(ArtsNetMatrixAggregatorMap & netmAggMap,
                       const Arts & arts, ofstream & out, float hours,
                       bool quiet) const
{
  vector<ArtsAttribute>::const_iterator     hostAttribute;
  vector<ArtsAttribute>::const_iterator     periodAttribute;
  vector<ArtsAttribute>::const_iterator     ifIndexAttribute;
  ArtsAggregatorMapKey                      netmKey;
  ArtsNetMatrixAggregatorMap::iterator      netmAggIter;
  static IntervalStartMap_t                 intervalStartMap;
  
  //  Add the data to the aggregator map.
  netmAggMap.Add(arts);
  
  hostAttribute = arts.FindHostAttribute();
  if (hostAttribute != arts.Attributes().end())
    netmKey.Router(hostAttribute->Host());
  else
    netmKey.Router(0);
  
  ifIndexAttribute = arts.FindIfIndexAttribute();
  if (ifIndexAttribute != arts.Attributes().end())
    netmKey.IfIndex(ifIndexAttribute->IfIndex());
  else
    netmKey.IfIndex(0);

  periodAttribute = arts.FindPeriodAttribute();
  if (intervalStartMap.find(netmKey) == intervalStartMap.end())
    intervalStartMap[netmKey] = ((*periodAttribute).Period())[0];

  if (hours > 0.0) {
    if ((periodAttribute->Period())[1] >
        (intervalStartMap[netmKey] + hours * 60 * 60)) {
      netmAggIter = netmAggMap.find(netmKey);
      if (netmAggIter != netmAggMap.end()) {
        ArtsNetMatrix *netMatrix =
          ((*netmAggIter).second)->ConvertToArtsNetMatrix();
        netMatrix->write(out);
        delete(netMatrix);
        delete((*netmAggIter).second);
        if (!quiet) {
          cout << "+";
          cout.flush();
        }
        intervalStartMap.erase(intervalStartMap.find(netmKey));
        netmAggMap.erase(netmAggIter);
      }
    }
  }
  return;
}

//----------------------------------------------------------------------------
//    void ArtsFileUtil::
//    AggregatePortMatrixData(ArtsPortMatrixAggregatorMap & portmAggMap,
//                            const Arts & arts, ofstream & out,
//                            float hours, bool quiet) const
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
AggregatePortMatrixData(ArtsPortMatrixAggregatorMap & portmAggMap,
                        const Arts & arts, ofstream & out,
                        float hours, bool quiet) const
{
  vector<ArtsAttribute>::const_iterator   hostAttribute;
  vector<ArtsAttribute>::const_iterator   periodAttribute;
  vector<ArtsAttribute>::const_iterator   ifIndexAttribute;
  ArtsAggregatorMapKey                    portmKey;
  ArtsPortMatrixAggregatorMap::iterator   portmAggIter;
  static IntervalStartMap_t               intervalStartMap;
  
  //  Add the data to the aggregator map.
  portmAggMap.Add(arts);
  
  hostAttribute = arts.FindHostAttribute();
  if (hostAttribute != arts.Attributes().end())
    portmKey.Router(hostAttribute->Host());
  else
    portmKey.Router(0);
  
  ifIndexAttribute = arts.FindIfIndexAttribute();
  if (ifIndexAttribute != arts.Attributes().end())
    portmKey.IfIndex(ifIndexAttribute->IfIndex());
  else
    portmKey.IfIndex(0);

  periodAttribute = arts.FindPeriodAttribute();
  if (intervalStartMap.find(portmKey) == intervalStartMap.end())
    intervalStartMap[portmKey] = ((*periodAttribute).Period())[0];

  if (hours > 0.0) {
    if ((periodAttribute->Period())[1] >
        (intervalStartMap[portmKey] + hours * 60 * 60)) {
      portmAggIter = portmAggMap.find(portmKey);
      if (portmAggIter != portmAggMap.end()) {
        if (this->_portChooser.PortChoices().size() != 0) {
          ArtsSelectedPortTable  *selectedPortTable =
            ((*portmAggIter).second)->ConvertToArtsSelectedPortTable(this->_portChooser);
          selectedPortTable->write(out);
          delete(selectedPortTable);
        }
        else {
          if (this->_numTopEntries > 0) {
            ArtsSelectedPortTable *selPortTable =
              ((*portmAggIter).second)->ConvertToArtsSelectedPortTable(this->_numTopEntries,false);
            selPortTable->write(out);
            delete(selPortTable);
          }
          else {
            ArtsPortMatrix *portMatrix =
              ((*portmAggIter).second)->ConvertToArtsPortMatrix();
            portMatrix->write(out);
            delete(portMatrix);
          }
        }
        
        delete((*portmAggIter).second);
        if (!quiet) {
          cout << "+";
          cout.flush();
        }
        intervalStartMap.erase(intervalStartMap.find(portmKey));
        portmAggMap.erase(portmAggIter);
      }
    }
  }
  return;
}

//----------------------------------------------------------------------------
//       bool ArtsFileUtil::
//       AggregateProtocolTables(const string & outFilename, 
//                               const vector<string> & inFilenames, 
//                               float hours, bool overwrite, 
//                               bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool ArtsFileUtil::AggregateProtocolTables(const string & outFilename,
                                           const vector<string> & inFilenames,
                                           float hours, bool overwrite,
                                           bool quiet) const
{
  ArtsProtocolTableAggregatorMap    protoAggMap;
  vector<string>::const_iterator    inFilenameIter;
  ofstream                         *out;
  ifstream                         *artsStream;

  //  open the output file.
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);
  if (!out || !(*out)) {
    cerr << "[E] unable to open '" << outFilename << "' as output file: "
         << strerror(errno) << endl;
    return(false);
  }
    
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open the input file.
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open '" << inFilenameIter->c_str()
           << "' as input file: " << strerror(errno) << endl;
      continue;
    }
    
    //  Use an istream_iterator to walk through ArtsProtocolTable
    //  objects in input file and aggregate them.
    istream_iterator<ArtsProtocolTable>  inStreamIter(*artsStream);
    istream_iterator<ArtsProtocolTable>  inStreamEnd;
    for (; inStreamIter != inStreamEnd; ++inStreamIter) {
      AggregateProtocolTableData(protoAggMap,*inStreamIter,*out,
                                 hours,quiet);
      if (!quiet) {
        cout << ".";
        cout.flush();
      }
    }

    delete(artsStream);
  }

  FinishProtocolTableAgg(protoAggMap,*out,quiet);
  out->close();
  delete(out);
  return(true);
}

//----------------------------------------------------------------------------
//  bool ArtsFileUtil::AggregateTosTables(const string & outFilename, 
//                                        const vector<string> & inFilenames, 
//                                        float hours, bool overwrite, 
//                                        bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool ArtsFileUtil::AggregateTosTables(const string & outFilename,
                                      const vector<string> & inFilenames,
                                      float hours, bool overwrite,
                                      bool quiet) const
{
  ArtsTosTableAggregatorMap         tosAggMap;
  vector<string>::const_iterator    inFilenameIter;
  ofstream                         *out;
  ifstream                         *artsStream;

  //  open the output file.
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);
  if (!out || !(*out)) {
    cerr << "[E] unable to open '" << outFilename << "' as output file: "
         << strerror(errno) << endl;
    return(false);
  }

  //  walk through the input files and aggregate.
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open the input file.
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open '" << inFilenameIter->c_str()
           << "' as input file: " << strerror(errno) << endl;
      continue;
    }

    //  Use an istream_iterator to walk through ArtsTosTable
    //  objects in input file and aggregate them.
    istream_iterator<ArtsTosTable>  inStreamIter(*artsStream);
    istream_iterator<ArtsTosTable>  inStreamEnd;
    for (; inStreamIter != inStreamEnd; ++inStreamIter) {
      AggregateTosTableData(tosAggMap,*inStreamIter,*out,
                            hours,quiet);
      if (!quiet) {
        cout << ".";
        cout.flush();
      }
    }

    delete(artsStream);
  }
  
  FinishTosTableAgg(tosAggMap,*out,quiet);
  out->close();
  delete(out);
  return(true);
}

//----------------------------------------------------------------------------
//  bool 
//  ArtsFileUtil::AggregateInterfaceMatrices(const string & outFilename, 
//                                         const vector<string> & inFilenames, 
//                                         float hours, bool overwrite, 
//                                         bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool
ArtsFileUtil::AggregateInterfaceMatrices(const string & outFilename,
                                         const vector<string> & inFilenames,
                                         float hours, bool overwrite,
                                         bool quiet) const
{
  ArtsInterfaceMatrixAggregatorMap   intfmAggMap;
  vector<string>::const_iterator     inFilenameIter;
  ofstream                          *out;
  ifstream                          *artsStream;

  //  open the output file.
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);
  if (!out || !(*out)) {
    cerr << "[E] unable to open '" << outFilename << "' as output file: "
         << strerror(errno) << endl;
    return(false);
  }
    
  //  walk through the input files and aggregate.
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open the input file.
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open '" << inFilenameIter->c_str()
           << "' as input file: " << strerror(errno) << endl;
      continue;
    }

    //  Use an istream_iterator to walk through ArtsInterfaceMatrix
    //  objects in input file and aggregate them.
    istream_iterator<ArtsInterfaceMatrix>  inStreamIter(*artsStream);
    istream_iterator<ArtsInterfaceMatrix>  inStreamEnd;
    for ( ; inStreamIter != inStreamEnd; ++inStreamIter) {
      AggregateInterfaceMatrixData(intfmAggMap,*inStreamIter,*out,
                                   hours,quiet);
      if (!quiet) {
        cout << ".";
        cout.flush();
      }
    }

    delete(artsStream);
  }
  
  FinishInterfaceMatrixAgg(intfmAggMap,*out,quiet);
  out->close();
  delete(out);
  return(true);
}

//----------------------------------------------------------------------------
//  bool 
//  ArtsFileUtil::AggregateNextHopTables(const string & outFilename, 
//                                       const vector<string> & inFilenames, 
//                                       float hours, bool overwrite, 
//                                       bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool
ArtsFileUtil::AggregateNextHopTables(const string & outFilename,
                                     const vector<string> & inFilenames,
                                     float hours, bool overwrite,
                                     bool quiet) const
{
  ArtsNextHopTableAggregatorMap     nexthopAggMap;
  vector<string>::const_iterator    inFilenameIter;
  ofstream                          *out;
  ifstream                          *artsStream;

  //  open the output file.
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);
  if (!out || !(*out)) {
    cerr << "[E] unable to open '" << outFilename << "' as output file: "
         << strerror(errno) << endl;
    return(false);
  }
    
  //  walk through the input files and aggregate.
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open the input file.
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open '" << inFilenameIter->c_str()
           << "' as input file: " << strerror(errno) << endl;
      continue;
    }

    //  Use an istream_iterator to walk through ArtsNextHopTable
    //  objects in input file and aggregate them.
    istream_iterator<ArtsNextHopTable>  inStreamIter(*artsStream);
    istream_iterator<ArtsNextHopTable>  inStreamEnd;
    for ( ; inStreamIter != inStreamEnd; ++inStreamIter) {
      AggregateNextHopTable(nexthopAggMap,*inStreamIter,*out,hours,quiet);
      if (!quiet) {
        cout << ".";
        cout.flush();
      }
    }

    delete(artsStream);
  }
  
  FinishNextHopTableAgg(nexthopAggMap,*out,quiet);
  out->close();
  delete(out);
  return(true);
}

//----------------------------------------------------------------------------
//   bool 
//   ArtsFileUtil::AggregateAsMatrices(const string & outFilename, 
//                                     const vector<string> & inFilenames, 
//                                     float hours, bool overwrite, 
//                                     bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool
ArtsFileUtil::AggregateAsMatrices(const string & outFilename,
                                  const vector<string> & inFilenames,
                                  float hours, bool overwrite,
                                  bool quiet) const
{
  ArtsAsMatrixAggregatorMap         asmAggMap;
  vector<string>::const_iterator    inFilenameIter;
  ofstream                          *out;
  ifstream                          *artsStream;

  //  open the output file
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);
  if (!out || !(*out)) {
    cerr << "[E] unable to open '" << outFilename << "' as output file: "
         << strerror(errno) << endl;
    return(false);
  }
    
  //  walk through the input files and aggregate.
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open the input file
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open '" << inFilenameIter->c_str()
           << "' as input file: " << strerror(errno) << endl;
      continue;
    }

    //  Use an istream_iterator to walk through ArtsAsMatrix
    //  objects in input file and aggregate them.
    istream_iterator<ArtsAsMatrix>  inStreamIter(*artsStream);
    istream_iterator<ArtsAsMatrix>  inStreamEnd;
    for (; inStreamIter != inStreamEnd; ++inStreamIter) {
      AggregateAsMatrixData(asmAggMap,*inStreamIter,*out,hours,quiet);
      if (!quiet) {
        cout << ".";
        cout.flush();
      }
    }
    
    delete(artsStream);
  }

  FinishAsMatrixAgg(asmAggMap,*out,quiet);
  out->close();
  delete(out);
  return(true);
}

//----------------------------------------------------------------------------
//   bool 
//   ArtsFileUtil::AggregateNetMatrices(const string & outFilename, 
//                                      const vector<string> & inFilenames, 
//                                      float hours, bool overwrite, 
//                                      bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool
ArtsFileUtil::AggregateNetMatrices(const string & outFilename,
                                   const vector<string> & inFilenames,
                                   float hours, bool overwrite,
                                   bool quiet) const
{
  ArtsNetMatrixAggregatorMap        netmAggMap;
  ofstream                          *out;
  ifstream                          *artsStream;
  
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);

  if (!out || !(*out)) {
    cerr << "[E] unable to open '" << outFilename << "' as output file: "
         << strerror(errno) << endl;
    return(false);
  }

  //  walk through the input files and aggregate.
  vector<string>::const_iterator   inFilenameIter;
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open input file
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open '" << inFilenameIter->c_str()
           << "' as input file: " << strerror(errno) << endl;
      continue;
    }

    //  Use an istream_iterator to walk through ArtsNetMatrix
    //  objects in input file and aggregate them.
    istream_iterator<ArtsNetMatrix>  inStreamIter(*artsStream);
    istream_iterator<ArtsNetMatrix>  inStreamEnd;
    for (; inStreamIter != inStreamEnd; ++inStreamIter) {
      AggregateNetMatrixData(netmAggMap,*inStreamIter,*out,hours,quiet);
      if (!quiet) {
        cout << ".";
        cout.flush();
      }
    }
    
    delete(artsStream);
  }

  FinishNetMatrixAgg(netmAggMap,*out,quiet);
  out->close();
  delete(out);
  return(true);
}

//----------------------------------------------------------------------------
//   bool 
//   ArtsFileUtil::AggregatePortMatrices(const string & outFilename, 
//                                const vector<string> & inFilenames, 
//                                float hours, bool overwrite, 
//                                bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool
ArtsFileUtil::AggregatePortMatrices(const string & outFilename,
                                    const vector<string> & inFilenames,
                                    float hours, bool overwrite,
                                    bool quiet) const
{
  ArtsPortMatrixAggregatorMap        portmAggMap;
  vector<string>::const_iterator     inFilenameIter;
  ofstream                          *out;
  ifstream                          *artsStream;

  //  open the output file.
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);
  if (!out || !(*out)) {
    cerr << "[E] unable to open '" << outFilename << "' as output file: "
         << strerror(errno) << endl;
    return(false);
  }

  //  walk through the input files and aggregate.
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open the input file
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open '" << inFilenameIter->c_str()
           << "' as input file: " << strerror(errno) << endl;
      continue;
    }

    //  Use an istream_iterator to walk through ArtsPortMatrix
    //  objects in input file and aggregate them.
    istream_iterator<ArtsPortMatrix>  inStreamIter(*artsStream);
    istream_iterator<ArtsPortMatrix>  inStreamEnd;
    for (; inStreamIter != inStreamEnd; ++inStreamIter) {
      AggregatePortMatrixData(portmAggMap,*inStreamIter,*out,hours,quiet);
      if (!quiet) {
        cout << ".";
        cout.flush();
      }
    }

    delete(artsStream);
  }
  FinishPortMatrixAgg(portmAggMap,*out,quiet);
  out->close();
  delete(out);

  return(true);
}

//----------------------------------------------------------------------------
//    bool ArtsFileUtil::Aggregate(const string & outFilename, 
//                                 const vector<string> & inFilenames, 
//                                 float hours, bool overwrite,
//                                 bool quiet) const 
//............................................................................
//  
//----------------------------------------------------------------------------
bool ArtsFileUtil::Aggregate(const string & outFilename,
                             const vector<string> & inFilenames,
                             float hours, bool overwrite,
                             bool quiet) const
{
  Arts                             *arts;
  ifstream                         *artsStream;
  ofstream                         *out;
  ArtsProtocolTableAggregatorMap    protoAggMap;
  ArtsInterfaceMatrixAggregatorMap  intfmAggMap;
  ArtsNextHopTableAggregatorMap     nextHopAggMap;
  ArtsAsMatrixAggregatorMap         asmAggMap;
  ArtsNetMatrixAggregatorMap        netmAggMap;
  ArtsPortMatrixAggregatorMap       portmAggMap;
  ArtsTosTableAggregatorMap         tosAggMap;

  
  if (overwrite)
    out = new ofstream(outFilename.c_str(),ios::out|ios::trunc);
  else
    out = new ofstream(outFilename.c_str(),ios::out|ios::app);

  if (!out || !(*out)) {
    cerr << "Failed to open output file '" << outFilename.c_str()
         << "' : " << strerror(errno) << " {" << __FILE__ << ":"
         << __LINE__ << "}" << endl;
    return(false);
  }
  
  vector<string>::const_iterator  inFilenameIter;

  //  walk through list of input files and aggregate.
  for (inFilenameIter = inFilenames.begin();
       inFilenameIter != inFilenames.end(); ++inFilenameIter) {
    //  open input file
    artsStream = new ifstream(inFilenameIter->c_str());
    if (!artsStream || !(*artsStream)) {
      cerr << "[E] unable to open input file '" << inFilenameIter->c_str()
           << "': " << strerror(errno) << endl;
      continue;
    }
    else {
      //  walk through input file and aggregate.
      while (*artsStream) {
        arts = new Arts();
        arts->Header().read(*artsStream);
        if ((! *artsStream) || (arts->Header().Magic() != artsC_MAGIC)) {
          delete(arts);
          break;
        }
        
        if (this->_objectTypeSelectionSet.size() > 0) {
          if (! this->_objectTypeSelectionSet.Matches(arts->Header().Identifier())) {
            artsStream->seekg(arts->Header().AttrLength()+
                              arts->Header().DataLength(),ios::cur);
            delete(arts);
            arts = (Arts *)0;
            continue;
          }
        }

        arts->Attributes().read(*artsStream,arts->Header().NumAttributes());
        if (! *artsStream) {
          delete(arts);
          arts = (Arts *)0;
          break;
        }
            
        if (this->_ifIndexSelectionSet.size() > 0) {
          vector<ArtsAttribute>::const_iterator ifIndexAttribute =
            arts->FindIfIndexAttribute();
          if (ifIndexAttribute == arts->Attributes().end()) {
            artsStream->seekg(arts->Header().DataLength(),ios::cur);
            delete(arts);
            arts = (Arts *)0;
            continue;
          }
          else {
            if (! this->_ifIndexSelectionSet.Matches((*ifIndexAttribute).IfIndex())) {
              artsStream->seekg(arts->Header().DataLength(),ios::cur);
              delete(arts);
              arts = (Arts *)0;
              continue;
            }
          }
        }

        if (this->_ifIndexCombineSet.size() > 0) {
          vector<ArtsAttribute>::const_iterator ifIndexAttribute =
            arts->FindIfIndexAttribute();
          if (ifIndexAttribute != arts->Attributes().end()) {
            if (this->_ifIndexCombineSet.Matches((*ifIndexAttribute).IfIndex())) {
              arts->RemoveIfDescrAttribute();
              arts->RemoveIfIpAddrAttribute();
              arts->RemoveIfIndexAttribute();
              arts->AddIfIndexAttribute(0);
            }
          }
        }
          
        arts->readData(*artsStream);
        if (! *artsStream) {
          delete(arts);
          arts = (Arts *)0;
          break;
        }

        switch (arts->Header().Identifier()) {
          case artsC_OBJECT_PROTO:
            if (!quiet) {
              cout << ".";
              cout.flush();
            }
            //  aggregate protocol table.
            AggregateProtocolTableData(protoAggMap,*arts,*out,hours,quiet);
            break;
            
          case artsC_OBJECT_TOS:
            if (!quiet) {
              cout << ".";
              cout.flush();
            }
            //  aggregate TOS table.
            AggregateTosTableData(tosAggMap,*arts,*out,hours,quiet);
            break;
            
          case artsC_OBJECT_INTERFACE_MATRIX:
            if (!quiet) {
              cout << ".";
              cout.flush();
            }
            //  aggregate interface matrix.
            AggregateInterfaceMatrixData(intfmAggMap,*arts,*out,hours,quiet);
            break;

          case artsC_OBJECT_NEXT_HOP:
            if (!quiet) {
              cout << ".";
              cout.flush();
            }
            //  aggregate nexthop table.
            AggregateNextHopTable(nextHopAggMap,*arts,*out,hours,quiet);
            break;
            
          case artsC_OBJECT_AS_MATRIX:
            if (!quiet) {
              cout << ".";
              cout.flush();
            }
            //  aggregate the AS matrix.
            AggregateAsMatrixData(asmAggMap,*arts,*out,hours,quiet);
            break;

          case artsC_OBJECT_NET:
            if (!quiet) {
              cout << ".";
              cout.flush();
            }
            //  aggregate the net matrix.
            AggregateNetMatrixData(netmAggMap,*arts,*out,hours,quiet);
            break;

          case artsC_OBJECT_PORT_MATRIX:
            if (!quiet) {
              cout << ".";
              cout.flush();
            }
            //  aggregate the port matrix.
            AggregatePortMatrixData(portmAggMap,*arts,*out,hours,quiet);
            break;
            
          default:
            break;
        }  // switch (artsHeader->Identifier()) ...
        delete(arts);
        arts = (Arts *)0;
      }  // while (*artsStream) ...
      artsStream->close();
    }
    delete(artsStream);
  }

  //  wrap up aggregation (finish final aggregation intervals which
  //  are not complete)
  FinishProtocolTableAgg(protoAggMap,*out,quiet);
  FinishTosTableAgg(tosAggMap,*out,quiet);
  FinishInterfaceMatrixAgg(intfmAggMap,*out,quiet);
  FinishNextHopTableAgg(nextHopAggMap,*out,quiet);
  FinishAsMatrixAgg(asmAggMap,*out,quiet);
  FinishNetMatrixAgg(netmAggMap,*out,quiet);
  FinishPortMatrixAgg(portmAggMap,*out,quiet);

  if (!quiet)
    cout << endl;
  
  out->close();
  delete(out);

  return(true);
}

//----------------------------------------------------------------------------
//        void ArtsFileUtil::
//        IfIndexSelectionSet(ArtsIfIndexSelectionSet & ifIndexSet) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
IfIndexSelectionSet(ArtsIfIndexSelectionSet & ifIndexSet)
{
  this->_ifIndexSelectionSet = ifIndexSet;
  return;
}

//----------------------------------------------------------------------------
//       void ArtsFileUtil::
//       IfIndexSelectionSet(const char *ifIndexSelectionExpression) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
IfIndexSelectionSet(const char *ifIndexSelectionExpression)
{
  this->_ifIndexSelectionSet.Load(ifIndexSelectionExpression);
  return;
}

//----------------------------------------------------------------------------
//          void ArtsFileUtil::
//          IfIndexCombineSet(ArtsIfIndexSelectionSet & ifIndexSet) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
IfIndexCombineSet(ArtsIfIndexSelectionSet & ifIndexSet)
{
  this->_ifIndexCombineSet = ifIndexSet;
  return;
}

//----------------------------------------------------------------------------
//        void ArtsFileUtil::
//        IfIndexCombineSet(const char *ifIndexSelectionExpression) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
IfIndexCombineSet(const char *ifIndexSelectionExpression)
{
  this->_ifIndexCombineSet.Load(ifIndexSelectionExpression);
  return;
}

//----------------------------------------------------------------------------
// void ArtsFileUtil:: 
// TimeIntervalSelectionSet(ArtsTimeIntervalSelectionSet & timeIntervalSet) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
TimeIntervalSelectionSet(ArtsTimeIntervalSelectionSet & timeIntervalSet)
{
  this->_timeIntervalSelectionSet = timeIntervalSet;
  return;
}

//----------------------------------------------------------------------------
//          void ArtsFileUtil:: 
//          TimeIntervalSelectionSet(const char *startTimeExpression, 
//                                   const char *endTimeExpression) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
TimeIntervalSelectionSet(const char *startTimeExpression,
                         const char *endTimeExpression)
{
  this->_timeIntervalSelectionSet.Load(startTimeExpression,
                                       endTimeExpression);
  return;
}

//----------------------------------------------------------------------------
//    void ArtsFileUtil:: 
//    ObjectTypeSelectionSet(ArtsObjectTypeSelectionSet & objectTypeSet) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
ObjectTypeSelectionSet(ArtsObjectTypeSelectionSet & objectTypeSet)
{
  this->_objectTypeSelectionSet = objectTypeSet;
  return;
}

//----------------------------------------------------------------------------
//      void ArtsFileUtil:: 
//      ObjectTypeSelectionSet(const char *objTypeSelectionExpression) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::
ObjectTypeSelectionSet(const char *objTypeSelectionExpression)
{
  this->_objectTypeSelectionSet.Load(objTypeSelectionExpression);
}

//----------------------------------------------------------------------------
//     void ArtsFileUtil::PortChooser(const char *portRangeExpression) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::PortChooser(const char *portRangeExpression)
{
  this->_portChooser.SetPorts(portRangeExpression);
  return;
}

//----------------------------------------------------------------------------
//     void ArtsFileUtil::NumberOfTopEntries(int numTopEntries) 
//............................................................................
//  
//----------------------------------------------------------------------------
void ArtsFileUtil::NumberOfTopEntries(int numTopEntries)
{
  this->_numTopEntries = numTopEntries;
  return;
}

uint32_t ArtsFileUtil::_numObjects = 0;
