/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

// File MvIconDataBase
// Gilberto Camara - ECMWF Jun 97
//
// .NAME:	
//  MvIconDataBase
//
// .AUTHOR:
//  Gilberto Camara and Fernando Ii
//
// .SUMMARY:
//  Implements a data base of Data Units and VisDefs
//  and a m:n relation between a DataUnit and a VisDef
//
//
#include <Assertions.hpp>
#include <MvPath.hpp>

#include "MvIconDataBase.h"
#include "MvLayer.h"
#include "MvRequestUtil.hpp"
#include "PlotModConst.h"
#include "Root.h"
#include "ObjectList.h"

MvIconDataBase::MvIconDataBase(const MvIconDataBase &old) :
  dataunitList_(old.dataunitList_),
  visdefList_(old.visdefList_),
  textList_(old.textList_),
  legendList_(old.legendList_),
  importList_(old.importList_)
{
}

MvIconDataBase::~MvIconDataBase()
{
   // Remove all data links
   DeleteLink();
}

// If presentable id is > 0, do the insertion into the presentable/
// dataunit relation also.
bool 
MvIconDataBase::InsertDataUnit ( MvIcon& newDataUnit,int presentableId)
{
   bool retVal = InsertIfNew(newDataUnit,dataunitList_,presentableDataUnitRelation_, presentableId);

   RelationInsertIfNew(presentableDataUnitRelation_,presentableId, newDataUnit.Id() );

   return retVal;
}

bool 
MvIconDataBase::InsertVisDef ( MvIcon& newVisDef)
{
	return InsertIfNew(newVisDef,visdefList_, presentableVisDefRelation_);
}

bool
MvIconDataBase::RetrieveVisDefList ( const MvIcon& dataUnit, MvIconList& visdefList )
{
	// Start from the beginning of the dataunit-visdef pairs
	this->DataUnitVisDefRelationRewind();

	MvIcon tmpVisDef;
	bool found = false;
	visdefList.clear();    //initialise list

	// Retrieve the VisDefs associated to the DataUnit
	while ( this->NextVisDefByDataUnitId ( dataUnit.Id(), tmpVisDef ) )
	{
		visdefList.push_back(tmpVisDef);
		found = true;
	}

	return found;
}

#if 0
void 
MvIconDataBase::RetrieveVisDefList ( MvIconList& dataUnitList, MvIconList& vdList)
{
	duListCursor_ = dataUnitList.begin();
	MvIcon theDataUnit;

	while ( duListCursor_ != dataUnitList.end() )
	{
		theDataUnit = *duListCursor_;

		RetrieveVisDefList ( theDataUnit, vdList );

		++duListCursor_;
	}
}

bool
MvIconDataBase::RetrieveDataUnitFromVisDef ( const int visdefId, MvIcon& theDataUnit)
{
	MvRelationCursor duvdCursor = dataUnitVisDefRelation_.begin();
        
	while (  duvdCursor != dataUnitVisDefRelation_.end() )
	{
              // VisDefs have a unique icon id 
	      // find the one on the list
	      if ( (*duvdCursor).second == visdefId )
	      {
	              // retrieve the dataunit Id
		      const int dataunitId = (*duvdCursor).first;

      		      // retrieve the dataunit
		      return RetrieveDataUnit(dataunitId, theDataUnit);
	      }
	      ++duvdCursor;
	}		      

	return false;
}
#endif

bool
MvIconDataBase::NextVisDefByDataUnitId (const int dataunitId, MvIcon& theVisDef)
{
	while (duvdRelationCursor_ !=  dataUnitVisDefRelation_.end())
	{
              // DataUnits have a unique icon id 
	      // find the one on the list
	      if ( (*duvdRelationCursor_).first == dataunitId )
	      {
	              // Retrieve the visdef Id
		      const int visdefId = (*duvdRelationCursor_).second;

		      // Increment the relation Cursor (to point to next item)
		      ++duvdRelationCursor_;

		      // Retrieve the visdef
		      //return RetrieveVisDef(visdefId, theVisDef);
            return RetrieveIconFromList(DB_VISDEF, visdefId, theVisDef);
	      }
	      ++duvdRelationCursor_;
	}

	return false;
}

#if 0
bool MvIconDataBase::DataUnitHasVisDef(const int dataUnitId,const int visdefId)
{
  bool retVal = false;

  if ( dataUnitId == 0 || visdefId == 0 )
    return retVal;

 MvIconList vdList;
 MvIcon dataUnit;

 RetrieveDataUnit(dataUnitId,dataUnit);
 RetrieveVisDefList(dataUnit,vdList);
 MvIcon currvd;

 for ( MvListCursor ii = vdList.begin(); ii != vdList.end(); ii++)
   {
     if ( (*ii).Id() == visdefId)
       {
	 retVal = true;
	 break;
       }
   }
 return retVal;
}
#endif

#if 0
bool
MvIconDataBase::NextDataUnitByClass (const Cached& iconClass, MvIcon& theDataUnit)
{
	while (duListCursor_ != dataunitList_.end())
	{
		if ( (*duListCursor_).IconClass() == iconClass )
		{
			theDataUnit = *duListCursor_;

		        ++duListCursor_;          // to point to next element
			return true;
		}
		++duListCursor_;
	}
return false;
}

bool
MvIconDataBase::NextDataUnit ( MvIcon& theDataUnit )
{
	if (duListCursor_ != dataunitList_.end())
	{
		theDataUnit = *duListCursor_;

		++duListCursor_;          // to point to next element
		return true;
	}
	return false;
}
#endif

bool
MvIconDataBase::RemoveAllVisDefsByDataUnit ( MvIcon& theDataUnit, const MvRequest* vd )
{
	bool found = false;

	MvRelationCursor duvdCursor = dataUnitVisDefRelation_.begin();
	MvRelationCursor foundCursor;

        MvIcon currentDataUnit;
	while (  duvdCursor != dataUnitVisDefRelation_.end() )
	{
      // DataUnits have a unique icon id. Find the one on the list.
      //RetrieveDataUnit((*duvdCursor).first,currentDataUnit);
      RetrieveIconFromList(DB_DATAUNIT,(*duvdCursor).first,currentDataUnit);

		if ( currentDataUnit.Id() == theDataUnit.Id() || 
		     currentDataUnit.ParentId() == theDataUnit.Id() )
		{
			// Keep a copy of the found iterator
			foundCursor = duvdCursor;

			// Increment, so we can continue our search
			++duvdCursor;

			MvIcon visDef;
			//RetrieveVisDef ( (*foundCursor).second, visDef );
         RetrieveIconFromList ( DB_VISDEF, (*foundCursor).second, visDef );

			// Do not remove if they are not of the same class
			if ( !vd || ObjectInfo::CheckVisDefClass(*vd, visDef.Request( )) )
			{ 
				// delete the relation pair
				dataUnitVisDefRelation_.erase ( foundCursor );

            // Remove visdef from list
            RemoveIconFromList ( DB_VISDEF, (*foundCursor).second );

				// indicate that visdef is related to dataunit
				found = true;
			}
		}
		else
			++duvdCursor;
	}

	return found;
}

void
MvIconDataBase::RemoveDataUnit ( MvIcon& theDataUnit )
{
   // Remove the visdef from the visdef-data unit relation
   RemoveAllVisDefsByDataUnit ( theDataUnit );

   // Remove data unit from the Presentable-DataUnit Relation
   RemoveAllDataUnitsFromPresRel (theDataUnit );

   // Remove data unit from List
   RemoveIconFromList ( DB_DATAUNIT,theDataUnit.Id() );
}

void
MvIconDataBase::RemoveDataUnit ( const int presentableId )
{
	// Retrieve list of DataUnits by presentable ID
	MvIconList dataUnitList;
	//DataUnitListByPresentableId ( presentableId, dataUnitList );
   RetrieveIcon ( PRES_DATAUNIT_REL, presentableId, dataUnitList );

	// Remove DataUnits
	MvListCursor duListCursor = dataUnitList.begin();
	while ( duListCursor != dataUnitList.end() )
	{
		RemoveDataUnit (*duListCursor);
		++duListCursor;
	}
}

void
MvIconDataBase::RemoveDataUnit ( )
{
	// Remove all DataUnits
	MvListCursor duListCursor = dataunitList_.begin();
	MvListCursor foundCursor;

	while ( duListCursor != dataunitList_.end() )
	{
		// Keep a copy of the found iterator
		foundCursor = duListCursor;

		// Increment, so we can continue our search
		++duListCursor;

		// Remove the visdef from the visdef-data unit relation
		RemoveAllVisDefsByDataUnit ( *foundCursor );

		// Remove data unit from the Presentable-DataUnit Relation
		RemoveAllDataUnitsFromPresRel ( *foundCursor );

		dataunitList_.erase ( foundCursor );
	}
}

bool
MvIconDataBase::RemoveAllDataUnitsFromPresRel ( MvIcon& theDataUnit )
{
	bool found = false;

	MvRelationCursor prduCursor = presentableDataUnitRelation_.begin();
	MvRelationCursor foundCursor;

	MvIcon currentDataUnit;
	while ( prduCursor != presentableDataUnitRelation_.end() )
	{
      //RetrieveDataUnit((*prduCursor).second,currentDataUnit);
      RetrieveIconFromList(DB_DATAUNIT,(*prduCursor).second,currentDataUnit);
		if ( currentDataUnit.Id() == theDataUnit.Id() || 
		     currentDataUnit.ParentId() == theDataUnit.Id() )
		{
			// Keep a copy of the found iterator
			foundCursor = prduCursor;

			// Increment, so we can continue our search
			++prduCursor;

			// Delete the relation pair
			presentableDataUnitRelation_.erase ( foundCursor );

			// Indicate that visdef is related to presentable
			found = true;
		}
		else
			++prduCursor;
	}

	return found;
}

bool
MvIconDataBase::RemoveDataUnitFromPresRel ( MvIcon& theDataUnit, int presentableId)
{
	bool found = false; 

	MvRelationCursor prduCursor = presentableDataUnitRelation_.begin();
	MvRelationCursor foundCursor;

	MvIcon currentDataUnit;
	while ( prduCursor != presentableDataUnitRelation_.end() )
	{
      //RetrieveDataUnit((*prduCursor).second,currentDataUnit);
      RetrieveIconFromList(DB_DATAUNIT,(*prduCursor).second,currentDataUnit);
		if ( (currentDataUnit.Id() == theDataUnit.Id() || 
		      currentDataUnit.ParentId() == theDataUnit.Id()) &&
		      (*prduCursor).first == presentableId )
		{
			// Keep a copy of the found iterator
			foundCursor = prduCursor;

			// delete the relation pair
			presentableDataUnitRelation_.erase ( foundCursor );

			// indicate that visdef is related to presentable
			found = true;
			break;
		}
		else
			++prduCursor;
	}

	return found;
}

#if 0
void
MvIconDataBase::RemoveVisDef ( MvIcon& theVisDef )
{
	bool found; 

	// Remove the visdef from the visdef-data unit relation

	found = RemoveAllVisDefsByVisDefId ( theVisDef );

	// If the visdef is not related to a data unit, then it must be
	// related to a presentable

	if ( found == false )
		RemoveAllVisDefsFromPresRel ( theVisDef );

	// Remove visdef

	RemoveVisDefFromList ( theVisDef.Id() );
}
#endif

void
MvIconDataBase::RemoveVisDef ( const int presentableId, const MvRequest* vd )
{
   // Remove VisDefs from DataUnit relation
   MvIconList dataUnitList;
   //if (DataUnitListByPresentableId ( presentableId, dataUnitList ))
   if (RetrieveIcon ( PRES_DATAUNIT_REL, presentableId, dataUnitList ))
      RemoveAllVisDefsByDataUnitList ( dataUnitList, vd );

   // Remove VisDefs from Presentable relation
   RemoveVisDefFromPresRel ( presentableId, vd );
}

void
MvIconDataBase::RemoveVisDefFromPresRel ( const int presentableId, const MvRequest* vd )
{
	MvRelationCursor prvdCursor =  presentableVisDefRelation_.begin();
	MvRelationCursor foundCursor;

	while (prvdCursor !=  presentableVisDefRelation_.end())
	{
              // Presentable have a unique icon id
	      // find the one on the list
	      if ( (*prvdCursor).first == presentableId )
	      {
		      foundCursor = prvdCursor;

		      // Increment the relation Cursor (to point to next item)
		      ++prvdCursor;

		      // Check if class is given
		      MvIcon theVisDef;
		      //if (vd && RetrieveVisDef((*foundCursor).second,theVisDef))
            if (vd && RetrieveIconFromList(DB_VISDEF,(*foundCursor).second,theVisDef))
		      {
			// Do not remove if they are not of the same class
			if (!ObjectInfo::CheckVisDefClass(*vd,theVisDef.Request()) )
			     continue;
		      }

            // Delete visdef from VisDefList
            RemoveIconFromList ( DB_VISDEF, (*foundCursor).second );

		      // Delete the visdef-presentable pair
		      presentableVisDefRelation_.erase ( foundCursor );
	      }
	      else
		      ++prvdCursor;
	}
}

void
MvIconDataBase::RemoveVisDef ( )
{
   bool found;

   // Remove all VisDefs
   MvListCursor vdListCursor = visdefList_.begin();
   MvListCursor foundCursor;
   while ( vdListCursor != visdefList_.end() )
   {
      // Keep a copy of the found iterator
      foundCursor = vdListCursor;

      // Increment, so we can continue our search
      ++vdListCursor;

      // Remove the visdef from the visdef-data unit relation
      found = RemoveIconFromRel ( DATAUNIT_VISDEF_REL, (*foundCursor).Id() );

      // If the visdef is not related to a data unit, then
      // it must be related to a presentable
      if ( found == false )
         RemoveIconFromRel ( PRES_VISDEF_REL, (*foundCursor).Id() );

      // delete the relation pair
      visdefList_.erase ( foundCursor );
   }
}

void
MvIconDataBase::RemoveAllVisDefsByDataUnitList ( MvIconList& dataUnitList, const MvRequest* vd )
{
   MvListCursor duListCursor = dataUnitList.begin();
	MvIcon theDataUnit;

	while ( duListCursor != dataUnitList.end() )
	{
		theDataUnit = *duListCursor;

		RemoveAllVisDefsByDataUnit ( theDataUnit, vd );

		++duListCursor;
	}
}

#if 0
void 
MvIconDataBase::PresentableVisDefRelation (const int presentableId, const int visdefId)
{
  RelationInsertIfNew(presentableVisDefRelation_,presentableId,visdefId);
}
#endif

bool
MvIconDataBase::VisDefListByDataUnitAndPresentableId ( const int   presentableId_, const char* dataUnitClass, MvIconList& visdefList )
{
	// Instantiate auxiliary variables
	MvIcon tmpVisDef;
	bool success = false;

	// Rewind the Presentable-VisDef relation
	this->PresentableVisDefRelationRewind();

	// Loop through the database and find all visdefs associated to
	// the superpage
	while ( this->NextVisDefByPresentableId ( presentableId_, tmpVisDef ) )
	{
                // Accept all valid visdefs
                if ( ObjectList::CheckValidVisDef ( dataUnitClass, tmpVisDef.IconClass() ) )
		{
			success = true;
			visdefList.push_back ( tmpVisDef );
		}
	}

	return success;
}

#if 0
bool
MvIconDataBase::VisDefListByPresentableId ( const int   presentableId, MvIconList& visdefList )
{
	// Instantiate auxiliary variables
	MvIcon tmpVisDef;
	bool success = false;

	// Rewind the Presentable-VisDef relation
	this->PresentableVisDefRelationRewind();

	// Loop through the database and find all visdefs associated to the presentable
	while ( this->NextVisDefByPresentableId ( presentableId, tmpVisDef ) )
	{
		success = true;
		visdefList.push_back ( tmpVisDef );
	}

	return success;
}
#endif

bool
MvIconDataBase::NextVisDefByPresentableId (const int presentableId, MvIcon& theVisDef)
{
	while (prvdRelationCursor_ !=  presentableVisDefRelation_.end())
	{
              // Presentable have a unique icon id 
	      // find the one on the list
	      if ( (*prvdRelationCursor_).first == presentableId )
	      {
	              // Retrieve the visdef Id
		      const int visdefId = (*prvdRelationCursor_).second;

		      // Increment the relation Cursor (to point to next item)
		      ++prvdRelationCursor_;

		      // Retrieve the visdef
		      //return RetrieveVisDef(visdefId, theVisDef);
            return RetrieveIconFromList(DB_VISDEF, visdefId, theVisDef);
	      }
	      ++prvdRelationCursor_;
	}

	return false;
}

#if 0
void
MvIconDataBase::UpdatePresentableVisDefRelation ( const int newPresentableId, const int oldPresentableId )
{
	int              visdefId;
	MvRelationCursor foundCursor;

	// Rewind the Presentable-VisDef relation
	this->PresentableVisDefRelationRewind();

	// Loop through the database and find all visdefs associated to
	// the presentable
	while (prvdRelationCursor_ !=  presentableVisDefRelation_.end())
	{
              // Presentable have a unique icon id 
	      // find the one on the list
	      if ( (*prvdRelationCursor_).first == oldPresentableId )
	      {
		      foundCursor = prvdRelationCursor_;
		      visdefId    = (*prvdRelationCursor_).second;

		      // delete the visdef-presentable pair
		      presentableVisDefRelation_.erase ( foundCursor );

	              // insert the new visdef-presentable pair
		      RelationInsertIfNew(presentableVisDefRelation_,newPresentableId,visdefId);
	      }
	      ++prvdRelationCursor_;
	}
}
#endif

#if 0
bool
MvIconDataBase::DataUnitListByPresentableId ( const int   presentableId, MvIconList& dataUnitList )
{
	// Instantiate auxiliary variables
	MvIcon tmpDataUnit;
	bool success = false;

	// Rewind the Presentable-DataUnit relation
	this->PresentableDataUnitRelationRewind();

	// Loop through the database and find all dataunits associated to
	// the superpage
	while ( this->NextDataUnitByPresentableId ( presentableId, tmpDataUnit ) )
	{
		success = true;
		dataUnitList.push_back ( tmpDataUnit );
	}

	return success;
}
#endif

bool
MvIconDataBase::PresentableHasData ( const int presentableId )
{
	// Instantiate auxiliary variables
	MvIcon tmpDataUnit;

	// Rewind the Presentable-DataUnit relation
	this->PresentableDataUnitRelationRewind();

	// Retrieve the first dataunit associated to the Presentable Id
	return this->NextDataUnitByPresentableId ( presentableId, tmpDataUnit );
}

bool
MvIconDataBase::NextDataUnitByPresentableId (const int presentableId, MvIcon& theDataUnit)
{
    while (prduRelationCursor_ !=  presentableDataUnitRelation_.end())
    {
        // Presentable have a unique icon id
        // find the one on the list
        if ( (*prduRelationCursor_).first == presentableId )
        {
             // Retrieve the dataunit Id
             const int dataunitId = (*prduRelationCursor_).second;

             // Increment the relation Cursor (to point to next item)
             ++prduRelationCursor_;

             // Retrieve the dataunit
             return RetrieveIconFromList ( DB_DATAUNIT, dataunitId, theDataUnit );
         }
         ++prduRelationCursor_;
   }

   return false;
}

#if 0
void
MvIconDataBase::UpdatePresentableDataUnitRelation ( const int newPresentableId, const int oldPresentableId )
{
	int              dataunitId;
	MvRelationCursor foundCursor;

	// Rewind the Presentable-DataUnit relation
	this->PresentableDataUnitRelationRewind();

	// Loop through the database and find all dataunits associated to
	// the presentable
	while (prduRelationCursor_ !=  presentableDataUnitRelation_.end())
	{
              // Presentable have a unique icon id 
	      // find the one on the list
	      if ( (*prduRelationCursor_).first == oldPresentableId )
	      {
		      foundCursor = prduRelationCursor_;
		      dataunitId    = (*prduRelationCursor_).second;

		      // delete the dataunit-presentable pair
		      presentableDataUnitRelation_.erase ( foundCursor );

	              // insert the new dataunit-presentable pair
		      RelationInsertIfNew(presentableDataUnitRelation_,newPresentableId,dataunitId);
	      }
	      ++prduRelationCursor_;
	}
}

void
MvIconDataBase::RemovePresentable (const int presentableId)
{
	require (presentableId > 0 );
	
	prvdRelationCursor_ = presentableVisDefRelation_.begin();
	
	while (prvdRelationCursor_ !=  presentableVisDefRelation_.end())
	{
              // Presentables have a unique icon id 
	      // find the one on the list
	      if ( (*prvdRelationCursor_).first == presentableId )
	      {
	              // delete this entry
		      presentableVisDefRelation_.erase(prvdRelationCursor_);
	      }
	      ++prvdRelationCursor_;
	}

}
#endif

MvIcon
MvIconDataBase::InsertDataUnit (  const MvRequest& dataunitRequest, int presentableId, int index )
{
	// Copy the grib Request into a new DataUnit
	MvIcon newDataUnit ( dataunitRequest );

   // If the data existed before, we get rid of old drawings to make sure
	// redraw is done properly
	if ( ! this->InsertDataUnit ( newDataUnit,presentableId ) )
	{
		if ( presentableId > 0 )
		{
			// Erase the segments to force redrawing
			Presentable* treeNode = Root::Instance().FindBranch (presentableId);
			bool oldStatus = treeNode->RemoveData();
			treeNode->RemoveData(false);
			treeNode->RemoveIcon(newDataUnit);
			treeNode->RemoveData(oldStatus);
		}
	}
	else
   {
      MvLayer layer;
      MvIcon icon(layer.Request(),true);
      this->InsertIcon( ICON_LAYER_REL,newDataUnit.Id(),icon, index );

   }

	return newDataUnit;
}

MvIcon
MvIconDataBase::InsertVisDef ( const MvRequest& visdefRequest,
			       const int         nodeId,
			       MvIcon&           dataUnit )
{
	require ( nodeId > 0 );
	require ( dataUnit.Id() >= 0 );

	// Copy the visdef Request into a new VisDef
	MvIcon visDef ( visdefRequest );

	int id;
	MvRelation *relation; // Pointer to avoid any copying of maps.

	// VisDefs that come after a DataUnit are assigned
	// to that DataUnit (or else they 
	// are assigned to the presentable)
	// NB Don't check validity of drop. This is responsibility of caller.
	if (  dataUnit.Id() > 0 )
	  {
	    id = dataUnit.Id();
	    relation = &dataUnitVisDefRelation_;
	  }
	else
	  {
	    id = nodeId;
	    relation = &presentableVisDefRelation_;
	  }

	// Put the visdef in the DataBase and in relation if it's not there
	if ( this->InsertIfNew(visDef,visdefList_,*relation,id) )
	  RelationInsertIfNew(*relation,id,visDef.Id() );

	return visDef;
}

void
MvIconDataBase::InsertVisDef ( MvIcon& visDef, const int nodeId )
{
	require ( nodeId > 0 );

	// Put the visdef in the DataBase and in relation if it's not there
	if ( this->InsertIfNew(visDef,visdefList_,presentableVisDefRelation_,nodeId) )
		RelationInsertIfNew( presentableVisDefRelation_,nodeId,visDef.Id() );

	return;
}

#if 0
int
MvIconDataBase::UpdateVisDefByName (const MvRequest& visdefRequest, const MvIcon& dataUnit)
{
	// Copy the visdef Request into a new VisDef icon
	MvIcon visDef ( visdefRequest );

	// Retrieve list of visdefs connect to the dataunit
	MvIconList vdList;
	if ( !RetrieveVisDefList(dataUnit,vdList) )
		return 0; //No relation found

	MvListCursor vdCursor = vdList.begin();
	while (vdCursor != vdList.end())
	{
		// Are the icons the "same" ?
		if (*vdCursor == visDef)
		{
			(*vdCursor).SaveRequest(visdefRequest,true);
			return (*vdCursor).Id();
		}

		++vdCursor;
	}

	return 0;
}

bool
MvIconDataBase::UpdateVisDefByName (const MvRequest& visdefRequest, const int nodeId, MvIconList& list, int option)
{
	require ( nodeId > 0 );

	// Copy the visdef Request into a new VisDef icon
	MvIcon visDef ( visdefRequest );

	// Search visdef list
	bool updated = false;
	MvListCursor vdCursor = visdefList_.begin();
	while (vdCursor != visdefList_.end())
	{
		// Are the icons the "same" ?
//		if (!CheckIconByNameAndType(*vdCursor,visDef))
		if (*vdCursor == visDef)
		{
			++vdCursor;
			continue;
		}

		// Update visdef at Presentable level
		if (option == DB_PRESENTABLE || option == DB_PRESENT_DU)
		{
			// Update if Presentable are the same
			if (ExistsInRelation( presentableVisDefRelation_,nodeId,(*vdCursor).Id()))
			{
				(*vdCursor).SaveRequest(visdefRequest,true);
				list.push_back((*vdCursor));
				updated = true;
				++vdCursor;
				continue;  //visdef is unique
			}
		}

		// Update visdef at DataUnit level
		if (option == DB_DATAUNIT || option == DB_PRESENT_DU)
		{
			// Check if visdef are related with dataunit
			MvIcon theDataUnit;
			if (RetrieveDataUnitFromVisDef ((*vdCursor).Id(),theDataUnit))
			{
				// Check if DataUnit are drawn in this Presentable
				if (ExistsInRelation( presentableDataUnitRelation_,nodeId,theDataUnit.Id()))
				{
				      (*vdCursor).SaveRequest(visdefRequest,true);
				      list.push_back((*vdCursor));
				      updated = true;
				}
			}
		}
		++vdCursor;
	}

	return updated;
}
#endif

// -----------------------------------------------------------------
// -- Methods for the Layers
// -----------------------------------------------------------------

bool
MvIconDataBase::UpdateLayerTransparency( int id, int value )
{
#if 0
    require ( id > 0 );

    // Layers have a unique icon id, find the one on the list
    MvListCursor layerListCursor = layerList_.begin();
    while (layerListCursor != layerList_.end())
    {
        if ( (*layerListCursor).Id() == id )
        {
            MvRequest req = (*layerListCursor).Request();
            req("TRANSPARENCY") = value;
            (*layerListCursor).SaveRequest(req,true);
            return true;
        }
        ++layerListCursor;
    }
#endif
    return false;
}

bool
MvIconDataBase::UpdateLayerVisibility( int id, bool onoff )
{
#if 0
    require ( id > 0 );

    // Layers have a unique icon id, find the one on the list
    layerListCursor_ = layerList_.begin();
    while (layerListCursor_ != layerList_.end())
    {
        if ( (*layerListCursor_).Id() == id )
        {
            MvRequest req = (*layerListCursor_).Request();
            req("VISIBILITY") = onoff;
            (*layerListCursor_).SaveRequest(req,true);
            return true;
        }
        ++layerListCursor_;
    }
#endif
    return false;
}

bool
MvIconDataBase::UpdateLayerStackingOrder ( )
{
    return false;
}

#if 0
void
MvIconDataBase::RemovePText ( MvIcon& thePText )
{
	// Remove PText from the Presentable-PText Relation

	RemoveAllPTextsFromPresRel (thePText );

	// Remove PText from List

	RemovePTextFromList ( thePText.Id() );
}

void
MvIconDataBase::RemoveText ( )  //replaced by RemoveIcon()
{
	// Remove all PTexts
	MvListCursor ptListCursor = textList_.begin();
	MvListCursor foundCursor;

	while ( ptListCursor != textList_.end() )
	{
		// Keep a copy of the found iterator
		foundCursor = ptListCursor;

		// Increment, so we can continue our search
		++ptListCursor;

		// Remove PText from the Presentable-PText Relation
		RemoveAllTextsFromPresRel ( *foundCursor );

		// delete the relation pair
		textList_.erase ( foundCursor );
	}
}
#endif

#if 0
void
MvIconDataBase::UpdatePresentablePTextRelation ( const int newPresentableId, const int oldPresentableId )
{
	int              ptextId;
	MvRelationCursor foundCursor;

	// Rewind the Presentable-PText relation
	this->PresentablePTextRelationRewind();

	// Loop through the database and find all ptexts associated to
	// the presentable
	while (prptRelationCursor_ !=  presentablePTextRelation_.end())
	{
              // Presentable have a unique icon id 
	      // find the one on the list
	      if ( (*prptRelationCursor_).first == oldPresentableId )
	      {
		      foundCursor = prptRelationCursor_;
		      ptextId    = (*prptRelationCursor_).second;

		      // delete the ptext-presentable pair
		      presentablePTextRelation_.erase ( foundCursor );

	              // insert the new ptext-presentable pair
		      RelationInsertIfNew(presentablePTextRelation_,newPresentableId,ptextId);
	      }
	      ++prptRelationCursor_;
	}
}
#endif

void
MvIconDataBase::RemoveAllData ( )
{
   RemoveDataUnit ( );               // remove all DataUnits
   RemoveVisDef ( );                 // remove all VisDefs
   RemoveIcon ( PRES_TEXT_REL );     // remove all Texts
   RemoveIcon ( PRES_LEGEND_REL );   // remove all Legends
   RemoveIcon ( PRES_IMPORT_REL );   // remove all Import objects
}

void
MvIconDataBase::RemovePresentable ( const int presentableId )
{
   // Remove all icons by Presentable Id
   RemoveDataUnit ( presentableId );
   RemoveVisDef ( presentableId );
   RemoveIcon ( PRES_TEXT_REL, presentableId );
   RemoveIcon ( PRES_LEGEND_REL, presentableId );
   RemoveIcon ( PRES_IMPORT_REL, presentableId );
}

void
MvIconDataBase::Print ()
{
   // Print lists
   cout << "MvIconDataBase Contents" << endl;
   string mlist[6] = {"DB_DATAUNIT", "DB_VISDEF", "DB_TEXT", "DB_LEGEND", "DB_LAYER", "DB_IMPORT"};
   for ( unsigned int i = 0; i < 6; i++)
   {
      cout << mlist[i] << endl;
      MvIconList* iconList = this->IconList(i);
      MvListCursor lCursor = iconList->begin();
      while (lCursor != iconList->end())
      {
         cout << " " << (*lCursor).Id();
         ++lCursor;
      }
      cout << " " << endl;
   }

   // Print relations
   cout << " " << endl;
   string mrel[7] = { "PRES_DATAUNIT_REL", "PRES_VISDEF_REL", "PRES_TEXT_REL", "PRES_LEGEND_REL", "ICON_LAYER_REL", "DATAUNIT_VISDEF_REL", "PRES_IMPORT_REL" };
   for ( unsigned int i = 0; i < 7; i++)
   {
      cout << mrel[i] << endl;
      MvRelation* rel = this->IconRelation(i);
      MvRelationCursor rCursor = rel->begin();
      while ( rCursor != rel->end() )
      {
         cout << " " << (*rCursor).first;
         cout << " " << (*rCursor).second << endl;
         ++rCursor;
      }
      cout << " " << endl;
   }

   // Print Presentable-Layer relation
   cout << "PRES_LAYER_REL" << endl;
   MvMapRelationCursor mCursor = presentableLayerRelation_.begin();
   while ( mCursor != presentableLayerRelation_.end() )
   {
      cout << " " << (*mCursor).first;
      MvIconList iconList = (*mCursor).second;
      MvListCursor listCursor = iconList.begin();
      while (listCursor != iconList.end())
      {
         MvIcon tmpIcon = *listCursor;
         cout << tmpIcon.Id();
         ++listCursor;
      }
      cout << endl;
      ++mCursor;
   }

   cout << " " << endl;
}

#if 0
void
MvIconDataBase::UpdatePresentable (const int newPresentableId, const int oldPresentableId )
{
	// Update all DataUnits related to a  Presentable Id
	UpdatePresentableDataUnitRelation ( newPresentableId, oldPresentableId );

	// Update all VisDefs relate to a Presentable Id
	UpdatePresentableVisDefRelation ( newPresentableId, oldPresentableId );

	// Update all PTexts related to a Presentable Id
	UpdatePresentablePTextRelation ( newPresentableId, oldPresentableId );
}
#endif

bool MvIconDataBase::InsertIfNew(MvIcon& icon,MvIconList &list,
				 MvRelation& relation,
				 int iconId)
{
	MvRequest newRequest = icon.Request();

	// It is important that the icon Id is added to the request:
	// newRequest("_ID") = xx . 
	// This will be used later when the request is passed to Magics

	// If no name, we can't check it's existence. Add it and return true
	const char *name = newRequest("_NAME");
	if ( ! name )
	{
		CreateLink (newRequest);
		icon.SaveRequest(newRequest,true);
		list.push_back(icon);
		return true;
	}

	// Loop through the list to find a match
	bool found = false;
	MvListCursor ii = list.begin();
	for ( ; ii != list.end(); ii++ )
	{
		MvIcon currentIcon = *ii;
		MvRequest currentRequest = currentIcon.Request();
		const char *currentName = currentRequest("_NAME");

		// Found a match on name. As the data units are
		// propagated downwards there may be more with 
		// same name. Check that this is the one beloning
		// to correct icon.
		if ( currentName && ! strcmp(currentName, name) )
		{
			if ( iconId == 0 || ( iconId > 0  && ExistsInRelation(relation,iconId,currentIcon.Id() ) ) )
			{
				CreateLink (newRequest);
				currentIcon.SaveRequest(newRequest,true);
				icon = currentIcon;
				found = true;
				break;
			}
		}
	}

	if ( ! found )
	{
		CreateLink (newRequest);
		icon.SaveRequest(newRequest,true);
		list.push_back(icon);
		return true;
	}

	return false;
}

void
MvIconDataBase::RelationInsertIfNew(MvRelation &relation,
				    const int firstId, const int secondId)
{
  if ( firstId == 0 || secondId == 0 )
    return;

  if ( ! ExistsInRelation(relation,firstId,secondId ) )
	relation.insert ( MvEntryPair (firstId, secondId));
}

bool MvIconDataBase::ExistsInRelation ( MvRelation &relation, const int firstId, const int secondId )
{
  // Check if this key and value is already there
  MvRelationCursor lower_ii = relation.lower_bound(firstId);
  MvRelationCursor upper_ii = relation.upper_bound(firstId);

  bool found = false;
  while ( lower_ii != relation.end() && lower_ii != upper_ii )
    {
      if ( (*lower_ii).second == secondId )
	{
	  found = true;
	  break;
	}
      lower_ii++;
    }

  return found;
}

void MvIconDataBase::CreateLink (MvRequest& req)
{
   // If there is no path, do no create a link
   const char* mpath = (const char*)(req("PATH"));
   if ( mpath == 0)
      return;

   // Check if the link has to be created
   const char* createLink = (const char*)req("_CREATE_LINK");
   if ( createLink && strcmp(createLink,"NO") == 0 )
      return;

   string spath = (const char*)mpath;
   string slink = tempnam(getenv("METVIEW_TMPDIR"),"link");

   if ( symlink(spath.c_str(),slink.c_str()) != 0 ) //-- create a soft link
   {
      marslog(LOG_WARN,(char*)"MvIconDataBase::CreateLink: unable to create a link");

      return; //-- nothing to do => bail out!
   }

   //-- make sure that soft link is not a dangling ptr!
   bool flag = true;
   if( !FileCanBeOpened( slink.c_str(), "r" ) )
   {
      // Try to use parameter _PATH
      if ( (const char*)req("_PATH") )
      {
         remove(slink.c_str());
         spath = (const char*)req("_PATH");
         symlink(spath.c_str(),slink.c_str());
         if ( !FileCanBeOpened( slink.c_str(), "r" ) )
            flag = false;
      }
      else
        flag = false;
   }
   if ( !flag )
   {
      marslog(LOG_WARN,(char*)"Created soft link is dangling: %s", slink.c_str());

      return; //-- nothing to do => bail out!
   }

   req("PATH") = slink.c_str();
   linkList_.push_back(slink.c_str());

   return;
}

void MvIconDataBase::DeleteLink ()
{
	list <string>::iterator listIter = linkList_.begin();

	while ( listIter != linkList_.end() )
	{
	      string mpath = (*listIter);
	      if ( unlink(mpath.c_str()) )
		     cout << "MvIconDataBase::DeleteLink : Error : Try to unlink a non existing file : " << mpath << endl;

	      ++listIter;
	}
}

// -----------------------------------------------------------------
// -- General methods
// -----------------------------------------------------------------

// Retrieve the relation pair variable
MvRelation* MvIconDataBase::IconRelation ( const int iconType )
{
    if ( iconType == DATAUNIT_VISDEF_REL )
        return &dataUnitVisDefRelation_;
    else if ( iconType == PRES_VISDEF_REL )
        return &presentableVisDefRelation_;
    else if ( iconType == PRES_DATAUNIT_REL )
        return &presentableDataUnitRelation_;
    else if ( iconType == PRES_TEXT_REL )
        return &presentableTextRelation_;
    else if ( iconType == PRES_LEGEND_REL )
        return &presentableLegendRelation_;
    else if ( iconType == ICON_LAYER_REL )
        return &iconLayerRelation_;
    else if ( iconType == PRES_IMPORT_REL )
        return &presentableImportRelation_;
    else
    {
        marslog(LOG_WARN,(char*)"Wrong type value for Icon Relation: %d", iconType);
        return NULL;
    }
}

// Retrieve the icon object list
MvIconList* MvIconDataBase::IconList ( const int iconType )
{
    if ( iconType == DB_DATAUNIT )
        return &dataunitList_;
    else if ( iconType == DB_VISDEF )
        return &visdefList_;
    else if ( iconType == DB_TEXT )
        return &textList_;
    else if ( iconType == DB_LEGEND )
        return &legendList_;
    else if ( iconType == DB_LAYER )
        return &layerList_;
    else if ( iconType == DB_IMPORT )
        return &importList_;
    else
    {
        marslog(LOG_WARN,(char*)"Wrong type value for Icon List: %d", iconType);
        return NULL;
    }
}

// Retrieve the correspondent icon type
int MvIconDataBase::IconType ( const int iconRelType )
{
    if ( iconRelType == DATAUNIT_VISDEF_REL )
        return DB_VISDEF;
    else if ( iconRelType == PRES_VISDEF_REL )
        return DB_VISDEF;
    else if ( iconRelType == PRES_DATAUNIT_REL )
        return DB_DATAUNIT;
    else if ( iconRelType == PRES_TEXT_REL )
        return DB_TEXT;
    else if ( iconRelType == PRES_LEGEND_REL )
        return DB_LEGEND;
    else if ( iconRelType == ICON_LAYER_REL )
        return DB_LAYER;
    else if ( iconRelType == PRES_IMPORT_REL )
        return DB_IMPORT;
    else
    {
        marslog(LOG_WARN,(char*)"Pair Icon Relation and Icon Type not defined: %d", iconRelType);
        return -1;
    }
}

void
MvIconDataBase::InsertIcon ( const int iconRelType, const int iconRelId, MvIcon& icon, bool bLayer, int index )
{
   // Insert icon
   this->InsertIcon( iconRelType,iconRelId,icon );

#if 1
   // Create a new Layer entry
   if ( bLayer )
   {
      MvLayer layer;
      layer.StackingOrder(index);
      //layer.IconId(icon.Id());
      MvIcon iconLayer(layer.Request(),true);
//      this->InsertMapIcon( ICON_LAYER_REL,icon.Id(),iconLayer,index );
      this->InsertLayerIcon( iconRelId,iconLayer,index );
   }
#endif
}

void
MvIconDataBase::InsertLayerIcon( const int presId, MvIcon& layer, int index )
{
  // Check if Layer already exists
   // Retrieve list of Layers by Presentable Id
   MvIconList layerList;
   if ( this->RetrieveLayerIcon1 ( presId, layerList ) )
   {
      // if index = 0 then add it in the beginning (background)
      // if index > list.size then add it in the end (foreground)
      // if index < 0 then add it in the end but before foreground
      // otherwise, add it in the position indicated by index
      int size = layerList.size();
      if ( index == 0 || size == 0 )
         layerList.push_front(layer);
      else if ( index > size )
         layerList.push_back(layer);
      else if ( index < 0 )
      {
         bool found = false;
         MvListCursor it = layerList.end();
         for ( int i = size; i != 0; --i )
         {
            --it;
            if ( (int)(*it).Request()("_STACKING_ORDER") != 999 )
            {
               layerList.insert(++it,layer);
               found = true;
               break;
            }
         }
         if ( !found ) // add as a first element
            layerList.push_front(layer);
      }
      else
      {
         MvListCursor it = layerList.begin();
         for ( int i = 1; i < index; i++) ++it;
         layerList.insert(it,layer);
      }
   }
}

int MvIconDataBase::RetrieveLayerIcon1 (const int ii,MvIconList& layerList)
{
   return 1;
}

void
MvIconDataBase::InsertIcon ( const int iconRelType, const int iconRelId, MvIcon& icon, int index, bool exclusive )
{
    require ( iconRelId > 0 );

    // Get the associated iconType from the icon relation type variable
    int iconType = IconType (iconRelType);

    // Retrieve list of icons by relation ID
    MvIconList iconList;
    if ( this->RetrieveIcon ( iconRelType, iconRelId, iconList ) )
    {
        // There are icons already associated to this relation
        // Check the flag indicating how to insert the new icon
        if ( exclusive )   // remove all existing icons before insert the new one
            this->RemoveIcon(iconRelType);
        else
        {
            // Scan list of icons to check if icon already exists
            MvListCursor listCursor = iconList.begin();
            while (listCursor != iconList.end())
            {
                MvIcon tmpIcon = *listCursor;
                if (tmpIcon == icon)
                {
                    // The icon exists in list. Update it taking into consideration the
                    // drawing order info.
                    MvRequest req;
                    CopyParametersAndStackingOrder ( tmpIcon.Request(), icon.Request(), index, req);
                    (*listCursor).SaveRequest(req,true);

                    return;
                }
                ++listCursor;
            }
        }
    }

    // Put the new icon in the correspondent List
    this->InsertIcon (iconType,icon,index);

    // Put the pair IconRel - Icon in the Relation
    this->InsertIconRelation ( iconRelType, iconRelId, icon.Id());

    return;
}

void
MvIconDataBase::InsertIcon ( const int iconType, const MvIcon& icon, int index )
{
   // if index = 0 then add it in the beginning (background)
   // if index > list.size then add it in the end (foreground)
   // if index < 0 then add it in the end but before foreground
   // otherwise, add it in the position indicated by index
   MvIconList* list = this->IconList( iconType );
   int size = list->size();
   if ( index == 0 || size == 0 )
      list->push_front(icon);
   else if ( index > size )
      list->push_back(icon);
   else if ( index < 0 )
   {
      bool found = false;
      MvListCursor it = list->end();
      for ( int i = size; i != 0; --i )
      {
         --it;
         if ( (int)(*it).Request()("_STACKING_ORDER") != 999 )
         {
            list->insert(++it,icon);
            found = true;
            break;
         }
      }
      if ( !found ) // add as a first element
         list->push_front(icon);
   }
   else
   {
      MvListCursor it = list->begin();
      for ( int i = 1; i < index; i++) ++it;
      list->insert(it,icon);
   }
}

void
MvIconDataBase::InsertIconText ( const int iconRelId, MvIcon& icon, int index )
{
    require ( iconRelId > 0 );

    // Get the associated iconType from the icon relation type variable
    int iconRelType = PRES_TEXT_REL;
    int iconType = IconType (iconRelType);

    // Flag indicating if the input icon is TITLE or POSITIONAL
    bool btitle = true;
    MvRequest iconRequest = icon.Request();
    if ( (const char*)iconRequest("TEXT_MODE") && 
         strcmp((const char*)iconRequest("TEXT_MODE"),"POSITIONAL") == 0 )
        btitle = false;

    // Retrieve list of icons by relation ID
    MvIconList iconList;
    if ( this->RetrieveIcon ( iconRelType, iconRelId, iconList ) )
    {
        // Find the icon on the list that is Text-Title
        MvListCursor listCursor = iconList.begin();
        while (listCursor != iconList.end())
        {
            MvIcon tmpIcon = *listCursor;
            MvRequest tmpRequest = tmpIcon.Request();
            if ( (const char*)tmpRequest("TEXT_MODE") && 
                 strcmp((const char*)tmpRequest("TEXT_MODE"),"POSITIONAL") == 0 )
            {
                // Icon is Positional
                if ( !btitle && tmpIcon == icon)
                {
                    // The icon exists in list. Update it taking into consideration the
                    // drawing order info.
                    MvRequest req;
                    CopyParametersAndStackingOrder ( tmpIcon.Request(), iconRequest, index, req);
                    (*listCursor).SaveRequest(req,true);

                    return;
                }
            }
            else  // found a Text-Title
            {
                if ( btitle )  // input icon is also Title
                {
                   RemoveIcon(iconRelType,iconRelId,tmpIcon.Id());
                   break;
                }
            }

            ++listCursor;
        }
    }

    // Put the new icon in the correspondent List
    this->InsertIcon (iconType,icon,index);

    // Put the pair IconRel - Icon in the Relation
    this->InsertIconRelation ( iconRelType, iconRelId, icon.Id());

    return;
}

void
MvIconDataBase::InsertIconRelation ( const int iconRelType, const int iconRelId, const int iconId)
{
    MvRelation* rel = this->IconRelation ( iconRelType );
    this->RelationInsertIfNew ( *rel,iconRelId,iconId );
}

bool
MvIconDataBase::RetrieveIcon( const int iconRelType, const int relId, MvIcon& theIcon )
{
    // Get the correspondent icon relation
    MvRelation* iconRelation = this->IconRelation(iconRelType);

    // Get the correspondent icon type
    int iconType = IconType(iconRelType);

    // Loop through the database and find the unique Layer associated to the Icon
    MvRelationCursor relCursor = iconRelation->begin();
    while (relCursor !=  iconRelation->end())
    {
        // Icon has a unique id; find the one on the list
        if ( (*relCursor).first == relId )
        {
            // Retrieve the icon Id
            const int iconId = (*relCursor).second;

            // Retrieve the icon
            return RetrieveIconFromList(iconType,iconId,theIcon);
        }
        ++relCursor;
    }

    return false;
}

int
MvIconDataBase::RetrieveIcon ( const int iconRelType, const int iconRelId, MvIconList& iconList )
{
   // Get the correspondent icon relation
   MvRelation* iconRelation = this->IconRelation(iconRelType);

   // Get the correspondent icon type
   int iconType = IconType(iconRelType);

   // Loop through the database and find all icons associated to the Presentable
   MvRelationCursor relCursor = iconRelation->begin();
   while (relCursor !=  iconRelation->end())
   {
       // Find the Presentable
       if ( (*relCursor).first == iconRelId )
       {
           // Retrieve the Icon Id
           const int iconId = (*relCursor).second;

          // Retrieve the icon
          MvIcon tmpIcon;
          if ( RetrieveIconFromList(iconType,iconId,tmpIcon) )
               iconList.push_back ( tmpIcon );
       }
       ++relCursor;
   }

   return iconList.size();
}

bool
MvIconDataBase::RetrieveIconFromList( const int iconType, const int iconId, MvIcon& theIcon)
{
    require ( iconId > 0 );

    // Get the correspondent icon list
    MvIconList* iconList = this->IconList(iconType);

    // Icons have a unique id; find the one on the list
    MvListCursor listCursor = iconList->begin();
    while (listCursor != iconList->end())
    {
        if ( (*listCursor).Id() == iconId )
        {
            theIcon = *listCursor;
            return true;
        }
        ++listCursor;
    }
    return false;
}

int
RetrieveLayerIcon ( const int presentableId, MvIconList& layerList )
{
   #if 0
   // Loop through the database and find all icons associated to the Presentable
   MvMapRelationCursor relCursor = presentableLayerRelation_.begin();


   while (relCursor !=  presentableLayerRelation_.end())
   {
       // Find the Presentable
       if ( (*relCursor).first == presentableId )
       {
          // Retrieve the layer list
          layerList = (*relCursor).second;
          break;
       }
       ++relCursor;
   }
#endif
//   return layerList.size();
return 0;
}

bool
MvIconDataBase::CheckIcon( const int iconRelType, const int relId )
{
    // Get the correspondent icon relation
    MvRelation* iconRelation = this->IconRelation(iconRelType);

    // Loop through the database and find the unique Layer associated to the Icon
    MvRelationCursor relCursor = iconRelation->begin();
    while (relCursor !=  iconRelation->end())
    {
        // Icon has a unique id; find the one on the list
        if ( (*relCursor).first == relId )
           return true;

        ++relCursor;
    }

    return false;
}

void
MvIconDataBase::RemoveIcon ( const int iconRelType )
{
   // Get the correspondent icon relation
   MvRelation* iconRelation = this->IconRelation(iconRelType);

   // Get the correspondent icon type
   int iconType = IconType(iconRelType);

   // Get the correspondent icon list
   MvIconList* iconList = this->IconList(iconType);

   // Remove all icons
   iconRelation->clear();
   iconList->clear();

   #if 0
   MvListCursor listCursor = iconList->begin();
   MvListCursor foundCursor;
   while ( listCursor != iconList->end() )
   {
      // Keep a copy of the found iterator
      foundCursor = listCursor;

      // Increment, so we can continue our search
      ++listCursor;

      // Delete the relation pair
      RemoveRelation ( *foundCursor );

      // Delete icon from List
      iconList->erase ( foundCursor );
   }
   #endif
}

void
MvIconDataBase::RemoveIcon ( const int iconRelType, const int iconRelId, const int iconIdIn )
{
   // Get the correspondent icon relation
   MvRelation* iconRelation = this->IconRelation(iconRelType);

   // Get the correspondent icon type
   int iconType = IconType(iconRelType);
   
   // Flag indicating if an specific icon or all icons will be deleted
   bool deleteOne = (iconIdIn >= 0) ? true : false;

   // Loop through the database and find all icons associated to the Relation icon
   MvRelationCursor relCursor = iconRelation->begin();
   MvRelationCursor foundCursor;
   while (relCursor !=  iconRelation->end())
   {
       if ( (*relCursor).first == iconRelId )
       {
           // Check if this icon is to be deleted
           if ( deleteOne && (*relCursor).second != iconIdIn )
           {
               ++relCursor;
               continue;
           }

           // Keep a copy of the found iterator
           foundCursor = relCursor;

           // Delete icon from List
           int iconId = (*foundCursor).second;
           RemoveIconFromList ( iconType, iconId );

           // Delete the relation pair
           iconRelation->erase ( foundCursor );

           // Delete entries in the Layer relation too
           if ( iconRelType != ICON_LAYER_REL )
              this->RemoveIcon(ICON_LAYER_REL,iconId);
       }

       ++relCursor;
   }
}

void
MvIconDataBase::RemoveIconFromList ( const int iconType, const int iconId )
{
   require ( iconId > 0 );

    // Get the correspondent icon list
    MvIconList* iconList = this->IconList(iconType);

   // Icons have a unique icon id; find the one on the list
   MvListCursor listCursor = iconList->begin();
   while ( listCursor != iconList->end() )
   {
      if ( (*listCursor).Id() == iconId )
      {
         iconList->erase ( listCursor );
         break;
      }
      ++listCursor;
   }
   return;
}

bool
MvIconDataBase::RemoveIconFromRel ( const int iconRelType, const int iconId )
{
   bool found = false;

   // Get the correspondent icon relation
   MvRelation* iconRelation = this->IconRelation(iconRelType);

   // Loop through the database and find all icons associated to the Relation icon
   MvRelationCursor relCursor = iconRelation->begin();
   MvRelationCursor foundCursor;
   while ( relCursor != iconRelation->end() )
   {
       if ( (*relCursor).second == iconId )
       {
           // Keep a copy of the found iterator
           foundCursor = relCursor;

           // Increment, so we can continue our search
           //++relCursor;

           // Delete the relation pair
           iconRelation->erase ( foundCursor );

           found = true;
       }
      //else
      ++relCursor;
   }

   return found;
}

bool
MvIconDataBase::UpdateIcon ( const int iconType, const int iconId, const MvRequest& iconRequest )
{
   require ( iconId > 0 );

   // Get the correspondent icon list
   MvIconList* iconList = this->IconList(iconType);

   // Icons have a unique id; find the one on the list
   MvListCursor listCursor = iconList->begin();
   while (listCursor != iconList->end())
   {
      if ( (*listCursor).Id() == iconId )
      {
         (*listCursor).SaveRequest(iconRequest,true);
         return true;
      }
      ++listCursor;
   }

   return false;
}
