/*	Author: Magdin Stoica
	Supervisor: Dr. Ryan Leduc
	
	Project created in conformity with the requirements for the Degree of Master of Engineering in Software Engineering, 
	Computing and Software Department, 
	McMaster University
	2003 - 2007
*/
#pragma once
#include <QMessageBox>
#include <QVariant>
#include <QFileInfo>
#include <QDir>
#include <QList>
#include "ProjectSerializer.h"
#include "DesFlatProject.h"
#include "DesHierProject.h"
#include "Des.h"
#include "xmlwriter.h"
#include "DesSerializer.h"
#include "MainForm.h"
#include "HierProjIntegrityAlgo.h"
#include "ProjectEditor.h"

// added by rjl - remove when bddhisc
// integrated with despot 

#include "ProjectEvent.h"
#include <iostream>
#include "Instantiation.h"
#include "TemplateNameParser.h"



namespace DESpot
{

const QString ProjectSerializer::cProjRootTag = "Project";
const QString ProjectSerializer::cProjFileVerAttr = "projVer";
const QString ProjectSerializer::cProjFileVerVal = "1.0.0";

const QString ProjectSerializer::cProjHeaderTag = "Header";
const QString ProjectSerializer::cProjNameAttr = "name";
const QString ProjectSerializer::cProjTypeAttr = "type";
const QString ProjectSerializer::cProjTypeFlatVal = "flat";
const QString ProjectSerializer::cProjTypeHierVal = "HISC";
const QString ProjectSerializer::cProjDegreeAttr = "degree";

const QString ProjectSerializer::cProjIntegrityTag = "Integrity";
const QString ProjectSerializer::cProjIntegStatusAttr = "status";
const QString ProjectSerializer::cProjIntegStatusYesVal = "yes";
const QString ProjectSerializer::cProjIntegStatusNoVal = "no";
const QString ProjectSerializer::cProjIntegStatusNotVerifVal = "not-verified";
const QString ProjectSerializer::cProjIntegStampAttr =  "date-stamp";

const QString ProjectSerializer::cProjNonBlockTag = "Nonblocking";
const QString ProjectSerializer::cProjNonBlockStatusAttr = "status";
const QString ProjectSerializer::cProjNonBlockPropYesVal = "yes";
const QString ProjectSerializer::cProjNonBlockPropNoVal = "no";
const QString ProjectSerializer::cProjNonBlockPropNotVerifVal = "not-verified";
const QString ProjectSerializer::cProjNonBlockStampAttr = "date-stamp";

const QString ProjectSerializer::cProjCtrlTag = "Controllable";
const QString ProjectSerializer::cProjCtrlStatusAttr = "status";
const QString ProjectSerializer::cProjCtrlPropYesVal = "yes";
const QString ProjectSerializer::cProjCtrlPropNoVal = "no";
const QString ProjectSerializer::cProjCtrlPropNotVerifVal = "not-verified";
const QString ProjectSerializer::cProjCtrlStampAttr = "date-stamp";

const QString ProjectSerializer::cProjIConsTag = "I-Consistent";
const QString ProjectSerializer::cProjIConsStatusAttr = "status";
const QString ProjectSerializer::cProjIConsPropYesVal = "yes";
const QString ProjectSerializer::cProjIConsPropNoVal = "no";
const QString ProjectSerializer::cProjIConsPropNotVerifVal = "not-verified";
const QString ProjectSerializer::cProjIConsStampAttr = "date-stamp";

const QString ProjectSerializer::cProjLwNonBlockTag = "LW-Nonblocking";
const QString ProjectSerializer::cProjLwNonBlockStatusAttr = "status";
const QString ProjectSerializer::cProjLwNonBlockPropYesVal = "yes";
const QString ProjectSerializer::cProjLwNonBlockPropNoVal = "no";
const QString ProjectSerializer::cProjLwNonBlockPropNotVerifVal = "not-verified";
const QString ProjectSerializer::cProjLwNonBlockStampAttr = "date-stamp";

const QString ProjectSerializer::cProjLwCtrlTag = "LW-Controllable";
const QString ProjectSerializer::cProjLwCtrlStatusAttr = "status";
const QString ProjectSerializer::cProjLwCtrlPropYesVal = "yes";
const QString ProjectSerializer::cProjLwCtrlPropNoVal = "no";
const QString ProjectSerializer::cProjLwCtrlPropNotVerifVal = "not-verified";
const QString ProjectSerializer::cProjLwCtrlStampAttr = "date-stamp";

const QString ProjectSerializer::cSubsysTag = "Subsystem";
const QString ProjectSerializer::cSubsysNameAttr = "name";
const QString ProjectSerializer::cSubsysLevelAttr = "level";
const QString ProjectSerializer::cSubsysValidStatusAttr = "valid";
const QString ProjectSerializer::cSubsysValidStatusYesVal = "yes";
const QString ProjectSerializer::cSubsysValidStatusNoVal = "no";
const QString ProjectSerializer::cSubsysLwCtrlProp = "lw-ctrl";
const QString ProjectSerializer::cSubsysLwCtrlYesVal = "yes";
const QString ProjectSerializer::cSubsysLwCtrlNoVal = "no";
const QString ProjectSerializer::cSubsysLwNonBlockProp = "lw-non-blocking";
const QString ProjectSerializer::cSubsysLwNonBlockYesVal = "yes";
const QString ProjectSerializer::cSubsysLwNonBlockNoVal = "no";
const QString ProjectSerializer::cSubsysIConsistProp = "i-consist";
const QString ProjectSerializer::cSubsysIConsistYesVal = "yes";
const QString ProjectSerializer::cSubsysIConsistNoVal = "no";

const QString ProjectSerializer::cSubsysImplTag = "Implements";

const QString ProjectSerializer::cInterfaceTag = "Interface";
const QString ProjectSerializer::cInterfRefTag = "InterfaceRef";
const QString ProjectSerializer::cInterfNameAttr = "name";
const QString ProjectSerializer::cInterfProviderAttr = "provider";
const QString ProjectSerializer::cInterfValidStatusAttr = "valid";
const QString ProjectSerializer::cInterfValidStatusYesVal = "yes";
const QString ProjectSerializer::cInterfValidStatusNoVal = "no";
const QString ProjectSerializer::cInterfIConsistProp = "i-consist";
const QString ProjectSerializer::cInterfIConsistYesVal = "yes";
const QString ProjectSerializer::cInterfIConsistNoVal = "no";

const QString ProjectSerializer::cInterfParentTag = "Parent";
const QString ProjectSerializer::cInterfParentNameAttr = "name";

const QString ProjectSerializer::cSubsysSupDesTag = "Supervisor";
const QString ProjectSerializer::cSubsysPlantDesTag = "Plant";
//add by bini
const QString ProjectSerializer::cSubsysTemplateDesTag = "Template";
const QString ProjectSerializer::cInterfaceTemplateDesTag = "InterfaceTemplate";

const QString ProjectSerializer::cSubsysTemplateTypeAttr = "Type";
const QString ProjectSerializer::cSubsysTemplateTypePlantVal = "P";
const QString ProjectSerializer::cSubsysTemplateTypeSupVal = "S";
const QString ProjectSerializer::cTemplateParameterTag="Parameter";
const QString ProjectSerializer::cTemplateParameterNameAttr="Name";
const QString ProjectSerializer::cTemplateParameterValueAttr="Value";
const QString ProjectSerializer::cInstantiationTag="Instantiation";
const QString ProjectSerializer::cInstInfoDlgNameAttr="DlgName";
const QString ProjectSerializer::cInstantiationInputType="InputType";
const QString ProjectSerializer::cSubsysInputTypeRangeVal="Range";
const QString ProjectSerializer::cSubsysInputTypeTupleVal="Tuple";

const QString ProjectSerializer::cSubsysUsesTag = "Uses";


const QString ProjectSerializer::cDesTag = "Des";
const QString ProjectSerializer::cDesNameAttr = "name";
const QString ProjectSerializer::cDesLocationAttr = "location";


//_________________________________________________________________________________________________

ProjectSerializer::ProjectSerializer() : 
		m_project(null), 
		m_crtSubsys(null),
		m_crtInterf(null),
		m_readingDesType(eNone),
		m_pError(null),
		m_integStatus(eIntegNotVerified),
		m_nonBlockStatus(eNonBlockNotVerified),
		m_ctrlStatus(eCtrlNotVerified),
		m_iConsStatus(eIConsNotVerified),
		m_lwNonBlockStatus(eLwNonBlockNotVerified),
		m_lwCtrlStatus(eLwCtrlNotVerified)
{
//add by bini
		if (m_parameter == null) 
	        m_parameter = new TemplateNameParser::TemplateParameter; 
}

//_________________________________________________________________________________________________

ProjectSerializer::ProjectSerializer(DesProject& project) : 
		m_project(&project), 
		m_crtSubsys(null),
		m_crtInterf(null),
		m_readingDesType(eNone),
		m_pError(null)
{
		//add by bini
		if (m_parameter == null) 
	        m_parameter = new TemplateNameParser::TemplateParameter; 
}

//_________________________________________________________________________________________________

ProjectSerializer::~ProjectSerializer(void)
{
	if (m_pError)
	{
		delete m_pError;
		m_pError = null;
	}
}

//_________________________________________________________________________________________________

DesProject* ProjectSerializer::load(const std::wstring& fileName)
{
	m_fileName = QString::fromStdWString(fileName);

	//open the file with the given file name
	QFile file(QString::fromStdWString(fileName));
	if (file.open(QIODevice::ReadOnly|QIODevice::Text) == false)
		throw EX("Cannot open file in read-only mode. Cannot load project.")

	//create and configure an XML Reader
	QXmlSimpleReader xmlReader;
	xmlReader.setContentHandler(this);
	//xmlReader.setErrorHandler(this);

	//...and have it parse the opened file
	QXmlInputSource* xmlSource = new QXmlInputSource(&file);
	bool sourceParsed = xmlReader.parse(xmlSource);

	if (sourceParsed == false)
	{
		throw new QXmlParseException(m_pError->message(), m_pError->columnNumber(), m_pError->lineNumber());
	}

	//the project was created and loaded
	return m_project;
}


// added by rjl - remove when bddhisc
// integrated with despot 
//_________________________________________________________________________________________________

void ProjectSerializer::exportToBDDhisc(const std::wstring& fileName)
{

	//-------------------------------------------------------------------------------------
	//THis peice of code is used to test the extraction system. You just need to change the name of node i. is subsysNode string
	// for which you want to extract the bi-level extraction system. Just make sure it is not a leaf node.
	// It is not the part of exportToBddhisc().
	/*DesHierProject::SubsysIteratorPtr tmpSybsysIt = hierProject()->createSubsysIterator();
	for(tmpSybsysIt->first(); tmpSybsysIt->notDone(); tmpSybsysIt->next())
		{
		const DesSubsystem& tempSubsys= tmpSybsysIt->currentItem();
		QString subsysNode= "Node0";
		if (tempSubsys.getName() == subsysNode.toStdWString())
		m_project =	extractionSystem(&tempSubsys);
		}*/
	//-------------------------------------------------------------------------------------

 //  this must never be called for a non hierarchical project.
  if(!(m_project->getType() == eHierProject))
    {
      throw EX("Can only export HISC projects to BDDhisc format.");
    }

 
  // bddhisc has a bug that it requires all uncontrollable events to
  // belong to at least one plant component. We need to ensure this.

  {
    DesProject::EventIteratorPtr  PeventIt = m_project->createProjEventIterator();
    DesSubsystem::DesIteratorPtr PdesIt = m_project->createDesIterator(ePlantDes);
    bool uevFound = false;

      for(PeventIt->first(); PeventIt->isDone() == false; PeventIt->next())
	{
	  const ProjectEvent& event = PeventIt->currentItem();

	  // add check to exclude low  data events for now as BddHisc
	  // does not support this for verification.  
	  if (event.getType() == eLDataEvent)
	    {
	      std::wstring message = L"Bddhisc does not currently support projects with Low Data events.";
	      throw message;
	    }


	  if (!(event.isControllable()))
	    {
	      std::wstring eName = event.getName();
	      uevFound = false;

	      // check if in a plant DES
	      for(PdesIt->first(); PdesIt->notDone(); PdesIt->next())
		{
		  Des& des = PdesIt->currentItem();
		  const DesEvent* event;
		  if (des.findEvent(eName,event))
		    {
		      uevFound = true;
		      break;
		    }
		}

	      if(!uevFound) 
		{
		  std::wstring message = L"Bddhisc requires that all uncontrollable events belong to at least one plant component.  Event \"";
		  message += eName;
		  message += L"\" does not.";
		  throw message;
		}
	    }

	}
  }


  //open the project file with the given file name
  QFile projFile(QString::fromStdWString(fileName));
  if (projFile.open(QIODevice::WriteOnly|QIODevice::Text) == false) {
    throw EX("Cannot open file in write-only mode. Cannot export project.");
  }

  //need to find out how many low-levels we have
  int numLow = hierProject()->getSubsystemCount() -1;

//first, get the highlevel
  const DesSubsystem& highSubsys = m_project->getRootSubsys();

  QString highName = QString::fromStdWString(highSubsys.getName());
  //  seems VC++ doesn't like: QString lowNames[numLow];
  QString * lowNames = new QString[numLow];

  // remove spaces from high name
  while (highName.contains(" "))
    {
      highName.remove(' ');
    }

  //write out project file
   QTextStream projOut(&projFile);

   //start writing the BDDhisc project file
   projOut << "[SYSTEM]\n";  
   projOut << QString::fromStdWString(m_project->getName()) << "\n\n";
   projOut << "[LOW]\n";
   projOut << numLow << "\n";

   // write out names of subsystems and record
   // add check for spaces
   int tmpNumLow = 0;
   DesHierProject::SubsysIteratorPtr subsysIt = hierProject()->createSubsysIterator();
   for(subsysIt->first(); subsysIt->notDone(); subsysIt->next())
     {
       const DesSubsystem& lowSubsys = subsysIt->currentItem();
			
       if (lowSubsys.isRoot() == false)
	 {
	   
           if (tmpNumLow >=numLow)
	     {
	       throw EX("Error: more subsystems present than recorded in subsystem count..");
	     }

	   lowNames[tmpNumLow] = QString::fromStdWString(lowSubsys.getName());

	   // remove spaces from name
	   while ((lowNames[tmpNumLow]).contains(" "))
	     {
	       (lowNames[tmpNumLow]).remove(' ');
	     }
	  projOut << lowNames[tmpNumLow] << "\n";
	   // write the isBilevelExtractionFlag to check if the subsys belong to Bilevel Extraction System. This has nothing to do with exportToBddHisc..
	  
	   QString bilevelExtracion = "N";
	   QString skipTest = "N";
	   if(lowSubsys.isBilevelExtraction())
	   bilevelExtracion = "Y";
	   else
	   bilevelExtracion="N";

	   if(lowSubsys.extractionSystemSkipTest())
		   skipTest= "Y";
	   else
		   skipTest="N";
	  projOut << "#( isBilevelExtration/extractionNonLeaf" << "\t" << bilevelExtracion << "/" << skipTest << ")" <<"\n";
	  tmpNumLow++;
	 }
     }
   projOut << "\n";
   projOut << "[HIGH]\n";
   projOut << highName <<"\n";
   // write the isBilevelExtractionFlag to check if the subsys belong to Bilevel Extraction System. This has nothing to do with exportToBddHisc..
	QString bilevelExtracion = "N";
	QString skipTest = "N";
	   if(highSubsys.isBilevelExtraction())
	   bilevelExtracion = "Y";
	   else
	   bilevelExtracion="N";
	   if(highSubsys.extractionSystemSkipTest())
		   skipTest= "Y";
	   else
		   skipTest="N";
	  projOut << "#( isBilevelExtration/extractionNonLeaf" << "\t" << bilevelExtracion << "/" << skipTest << ")" <<"\n";
	 
   // project file complete. Export high subsystem
   QString absPath = QFileInfo(projFile).absolutePath();
   QString highPath = absPath + QDir::separator() + highName;
   QString highSubsysFileName = highPath  + QDir::separator()  + highName  + ".sub";

  QDir projDir(absPath);
  projDir.mkdir(highName);
  QFile highFile(highSubsysFileName);
  if (highFile.open(QIODevice::WriteOnly|QIODevice::Text) == false) {
    throw EX("Cannot open high subsystem file in write-only mode. Cannot export project.");
  }

  QTextStream highOut(&highFile);

  highOut << "[SYSTEM]"  << "\n";

  int numPlants = 0;
  int numSups = 0;

  // count number of plants
  {
    DesSubsystem::DesIteratorPtr desIt = highSubsys.createDesIterator(ePlantDes);
    for(desIt->first(); desIt->notDone(); desIt->next())
      {
	numPlants++;
      }
  }
  highOut << numPlants  << "\n";

  // count number of Sups
  {
    DesSubsystem::DesIteratorPtr desIt = highSubsys.createDesIterator(eSupervisorDes);
    for(desIt->first(); desIt->notDone(); desIt->next())
      {
	numSups++;
      }
  }
  highOut << numSups  << "\n\n";

  highOut << "[PLANT]"  << "\n";

  //list the plant DES
  {
    DesSubsystem::DesIteratorPtr desIt = highSubsys.createDesIterator(ePlantDes);
    for(desIt->first(); desIt->notDone(); desIt->next())
      {
	Des& des = desIt->currentItem();
	QString highDESName = QString::fromStdWString(des.getName()) + ".hsc";
	highOut <<  highDESName  <<"\n";
	QString highDESFileName = highPath  + QDir::separator() + highDESName;
	std::wstring tmpFileName = highDESFileName.toStdWString();
	des.exportToBDDhiscORsd(tmpFileName,true,true);
      }
  }
  highOut << "\n[SPEC]"  << "\n";

  //list the sup DES
  {
    DesSubsystem::DesIteratorPtr desIt = highSubsys.createDesIterator(eSupervisorDes);
    for(desIt->first(); desIt->notDone(); desIt->next())
      {
	Des& des = desIt->currentItem();
	QString highDESName = QString::fromStdWString(des.getName()) + ".hsc";
	highOut << highDESName  <<"\n";
	QString highDESFileName = highPath  + QDir::separator() + highDESName;
	std::wstring tmpFileName = highDESFileName.toStdWString();
	des.exportToBDDhiscORsd(tmpFileName,true,true);
      }
  }

  //  the high subsystem file is now complete


   // export low level subsystems
  //  seems VC++ doesn't like: QString lowPaths[numLow];
   QString * lowPaths =  new QString[numLow];
   // seems VC++ doesn't like: QString lowSubsysFileNames[numLow];
   QString * lowSubsysFileNames =  new QString[numLow];

   for (int i = 0; i < numLow;i++) 
     {
        lowPaths[i] =  absPath + QDir::separator() + lowNames[i];
        lowSubsysFileNames[i] = lowPaths[i] + QDir::separator() +   lowNames[i] +  ".sub";
	projDir.mkdir(lowNames[i]);
     }

   // need to loop through the low subystems and export them.
   tmpNumLow = 0;
   for(subsysIt->first(); subsysIt->notDone(); subsysIt->next())
     {
       const DesSubsystem& lowSubsys = subsysIt->currentItem();
			
       if (lowSubsys.isRoot() == false)
	 {
	   QFile lowFile(lowSubsysFileNames[tmpNumLow]);
	   if (lowFile.open(QIODevice::WriteOnly|QIODevice::Text) == false) {
	     throw EX("Cannot open low subsystem file in write-only mode. Cannot export project.");
	   }

	   QTextStream lowOut(&lowFile);
	   lowOut << "[SYSTEM]"  << "\n";

	   numPlants = 0;
	   numSups = 0;
	   // count number of plants
	   {
	     DesSubsystem::DesIteratorPtr desIt = lowSubsys.createDesIterator(ePlantDes);
	     for(desIt->first(); desIt->notDone(); desIt->next())
	       {
		 numPlants++;
	       }
	   }
	   lowOut << numPlants  << "\n";

	   // count number of Sups
	   {
	     DesSubsystem::DesIteratorPtr desIt = lowSubsys.createDesIterator(eSupervisorDes);
	     for(desIt->first(); desIt->notDone(); desIt->next())
	       {
		 numSups++;
	       }
	   }
	   lowOut << numSups  << "\n\n";

	   lowOut << "[INTERFACE]"  << "\n";

	   if (lowSubsys.implementsInterface())
	     {
	       const DesInterface& interf = lowSubsys.getInterface();
	       
	       int numIntfDes = 0;
	       {
		 //  count number of intf DES
		 DesInterface::DesIteratorPtr desIt = interf.createDesIterator();
		 for(desIt->first(); desIt->notDone(); desIt->next())
		   {
		     numIntfDes++;
		   }
	       }

	       if ( numIntfDes >1) 
		 {
		   // BDDhisc only allows one intf des, so we need to
		   // first sync them together.
		   Des& intfDes = interf.getSyncDes();
		   QString intfDESName = QString::fromStdWString(intfDes.getName()) + ".hsc";
		   lowOut << intfDESName  <<"\n";
		   QString intfDESFileName = lowPaths[tmpNumLow]  + QDir::separator() + intfDESName;
		   std::wstring tmpIntfFileName = intfDESFileName.toStdWString();
		   intfDes.exportToBDDhiscORsd(tmpIntfFileName,false,true);
		 }
	       else
		 {
		   // loop through interface des. bddhisc only allows one.
		   DesInterface::DesIteratorPtr desIt = interf.createDesIterator();
		   for(desIt->first(); desIt->notDone(); desIt->next())
		     {
		       Des& intfDes = desIt->currentItem();
		       QString intfDESName = QString::fromStdWString(intfDes.getName()) + ".hsc";
		       lowOut << intfDESName  <<"\n";
		       QString intfDESFileName = lowPaths[tmpNumLow]  + QDir::separator() + intfDESName;
		       std::wstring tmpIntfFileName = intfDESFileName.toStdWString();
		       intfDes.exportToBDDhiscORsd(tmpIntfFileName,false,true);
		     }
		 }
	     }
	  

	   lowOut << "\n[PLANT]"  << "\n";

	   //list the plant DES
	   {
	     DesSubsystem::DesIteratorPtr desIt = lowSubsys.createDesIterator(ePlantDes);
	     for(desIt->first(); desIt->notDone(); desIt->next())
	       {
		 Des& des = desIt->currentItem();
		 QString lowDESName = QString::fromStdWString(des.getName()) + ".hsc";
		 lowOut << lowDESName  <<"\n";
		 QString lowDESFileName = lowPaths[tmpNumLow]  + QDir::separator() + lowDESName;
		 std::wstring tmpFileName = lowDESFileName.toStdWString();
		 des.exportToBDDhiscORsd(tmpFileName,false,true);
	       }
	   }
	   lowOut << "\n[SPEC]"  << "\n";

	   //list the sup DES
	   {
	     DesSubsystem::DesIteratorPtr desIt = lowSubsys.createDesIterator(eSupervisorDes);
	     for(desIt->first(); desIt->notDone(); desIt->next())
	       {
		 Des& des = desIt->currentItem();
		 QString lowDESName = QString::fromStdWString(des.getName()) + ".hsc";
		 lowOut << lowDESName  <<"\n";
		 QString lowDESFileName = lowPaths[tmpNumLow]  + QDir::separator() + lowDESName;
		 std::wstring tmpFileName = lowDESFileName.toStdWString();
		 des.exportToBDDhiscORsd(tmpFileName,false,true);
	       }
	   }

	   tmpNumLow++;
	 }
     }

   //that should do it.

}

//  remove to here - RJL


// added by rjl - remove when bddsd
// integrated with despot 
//_________________________________________________________________________________________________

void ProjectSerializer::exportToBDDsd(const std::wstring& fileName)
{

  //  this must never be called for a non flat project.
  if(!(m_project->getType() == eFlatProject))
    {
      throw EX("Can only export flat projects to BDDsd format.");
    }

  // need to add here a check that all DES contain a controllable
  // event with name "tick" and alias "t"

  {
    DesSubsystem::DesIteratorPtr PdesIt = m_project->createDesIterator();
    std::wstring tName = L"tick";
    std::wstring tAlias = L"t";
    bool fndEvent = false;


    for(PdesIt->first(); PdesIt->notDone(); PdesIt->next())
      {
	Des& des = PdesIt->currentItem();
	const DesEvent* event;
        fndEvent = false;

	if (des.findEvent(tName,event))
	  {
	    std::wstring tmpAlias = event->getAlias();
	    if ((tAlias == tmpAlias) && (event->isControllable()))
	      {
		fndEvent = true;
	      }
	  } 

	if (!fndEvent)
	  {
	    std::wstring message = L"Bddsd requires that every DES\
 contain a controllable event named \"tick\" with alias\
 \"t\". DES \"";
	    message += des.getName();
	    message += L"\" does not.";
	    throw message;
	  }

      }

  }



  
  //open the project file with the given file name
  QFile projFile(QString::fromStdWString(fileName));
  if (projFile.open(QIODevice::WriteOnly|QIODevice::Text) == false) {
    throw EX("Cannot open file in write-only mode. Cannot export project.");
  }

  //write out project file
   QTextStream projOut(&projFile);

   // Determ directory path to put DES files in
   QString absPath = QFileInfo(projFile).absolutePath();

   projOut << "[SYSTEM]"  << "\n";

   int numPlants = 0;
   int numSups = 0;

   // count number of plants
   {
     DesSubsystem::DesIteratorPtr desIt = m_project->createDesIterator(ePlantDes);
     for(desIt->first(); desIt->notDone(); desIt->next())
       {
	 numPlants++;
       }
   }
   projOut  << numPlants  << "\n";

   // count number of Sups
   {
     DesSubsystem::DesIteratorPtr desIt = m_project->createDesIterator(eSupervisorDes);
     for(desIt->first(); desIt->notDone(); desIt->next())
       {
	 numSups++;
       }
   }
   projOut  << numSups  << "\n\n";

   projOut  << "[PLANT]"  << "\n";

   //list the plant DES
   {
     DesSubsystem::DesIteratorPtr desIt = m_project->createDesIterator(ePlantDes);
     for(desIt->first(); desIt->notDone(); desIt->next())
       {
	 Des& des = desIt->currentItem();
	 QString DESName = QString::fromStdWString(des.getName()) + ".hsc";
	 projOut  <<  DESName  <<"\n";
	 QString DESFileName = absPath  + QDir::separator() + DESName;
	 std::wstring tmpFileName = DESFileName.toStdWString();
	 des.exportToBDDhiscORsd(tmpFileName,false,false);
       }
   }
   projOut  << "\n[SPEC]"  << "\n";

   //list the sup DES
   {
     DesSubsystem::DesIteratorPtr desIt = m_project->createDesIterator(eSupervisorDes);
     for(desIt->first(); desIt->notDone(); desIt->next())
       {
	 Des& des = desIt->currentItem();
	 QString DESName = QString::fromStdWString(des.getName()) + ".hsc";
	 projOut  << DESName  <<"\n";
	 QString DESFileName = absPath  + QDir::separator() + DESName;
	 std::wstring tmpFileName = DESFileName.toStdWString();
	 des.exportToBDDhiscORsd(tmpFileName,false,false);
       }
   }

   //that should do it.

}

//  remove to here - RJL


//_________________________________________________________________________________________________

void ProjectSerializer::save(const std::wstring& fileName)
{
	m_fileName = QString::fromStdWString(fileName);

	//open the file with the given file name
	QFile file(QString::fromStdWString(fileName));
	if (file.open(QIODevice::WriteOnly|QIODevice::Text) == false)
		throw EX("Cannot open file in write-only mode. Cannot save DES.")

	//create an XML serializer
	XmlWriter xw(file);
	xw.setAutoNewLine(true);

	//start writing the file
	xw.writeOpenTag(cProjRootTag, AttrMap(cProjFileVerAttr, cProjFileVerVal));

	//write the definition of the project
	writeProjDefinition(xw);
	
	//write the end of the file
	xw.writeCloseTag(cProjRootTag);
}

//_________________________________________________________________________________________________

void ProjectSerializer::configure(ProjSerializerAccess* projAccess)
{
	m_projectAccess = projAccess;
}

//_________________________________________________________________________________________________

//the parsing is starting
bool ProjectSerializer::startDocument()
{
	//clean any errors from previous parses
	if (m_pError)
	{
		delete m_pError;
		m_pError = null;
	}

	//clear any information that may have been previously loaded
	m_projFileVer.clear();

	return true;
}

//_________________________________________________________________________________________________

bool ProjectSerializer::endDocument()
{
	if (m_project == null)
	{
		throw EX("Invalid project file. Cannot load project");
	}
	
	//set project properties
	setProjectProperties();

	if (m_project->getType() == eHierProject)
	{
		resolveInterfImplementations();
		resolveSubsysDependencies();
		resolveInterfParent();
	}

	//tell the project we're done loading it
	m_projectAccess->setLoadInProgress(false);

	return true;
}

//_________________________________________________________________________________________________
//modified by bini
//element and attribute parsing
bool ProjectSerializer::startElement(const QString& /*namespaceURI*/, const QString& localName, 
									 const QString& /*qName*/, const QXmlAttributes& atts)
{
	if (localName == cProjRootTag)
	{
		return readProjectRoot(localName, atts);
	}
	

	else 
	{
		return readProjectDefinition(localName, atts);
	}

}

//_________________________________________________________________________________________________

bool ProjectSerializer::endElement(const QString& /*namespaceURI*/, const QString& localName, 
								   const QString& /*qName*/)
{
	if (localName == cSubsysTag)
	{
		m_crtSubsys->setLoadInProgress(false);
	}
	else if (localName == cInterfaceTag)
	{
		m_crtInterf->setLoadInProgress(false);
	}
	else if (localName == cInstantiationTag) 
	{ 
		if(m_project->getType() == eFlatProject)
		{
			((DesFlatProject*)m_project)->addInstantiation(m_inst, m_des); 
			m_project->onInstAdded(*m_inst,*m_des);
		}
		else if(m_project->getType() == eHierProject)
		{
			((DesHierProject*)m_project)->addInstantiation(m_inst, m_des); 
			m_project->onInstAdded(*m_inst,*m_des);
		}
		
    	} 
    	else if (localName == cTemplateParameterTag) 
    	{ 
 		
    	} 

	return true;
}

//_________________________________________________________________________________________________

//error handling
bool ProjectSerializer::warning(const QXmlParseException& exception)
{
	qWarning(exception.message().toAscii().data());
	return true; //continue
}

//_________________________________________________________________________________________________

bool ProjectSerializer::error(const QXmlParseException& exception)
{
	assert(m_pError == null);
	m_pError = new QXmlParseException(exception.message(), exception.columnNumber(), exception.lineNumber());
	
	qWarning(exception.message().toAscii().data());
	
	return false; //stop parsing
}

//_________________________________________________________________________________________________

bool ProjectSerializer::fatalError(const QXmlParseException& exception)
{
	assert(m_pError == null);
	m_pError = new QXmlParseException(exception.message(), exception.columnNumber(), exception.lineNumber());	

	qWarning(exception.message().toAscii().data());
	
	return false; //stop parsing
}

//_________________________________________________________________________________________________

void ProjectSerializer::createProject(ProjectType projType, QString projName)
{
	switch(projType)
	{
		case eFlatProject:
			m_project = new DesFlatProject(projName.toStdWString());
			break;

		case eHierProject:
			m_project = new DesHierProject(projName.toStdWString());
			break;
	}

	m_project->configureSerializer(this);
	m_projectAccess->setLoadInProgress();
}

//_________________________________________________________________________________________________

DesFlatProject* ProjectSerializer::flatProject()
{
	assert(m_project != null);
	assert(m_project->getType() == eFlatProject);
	DesFlatProject* flatProject = dynamic_cast<DesFlatProject*>(m_project);
	
	if (flatProject == null)
	{		  
		throw EX("The project beeing loaded is not a flat project");
	}

	return flatProject;
}

//_________________________________________________________________________________________________

DesHierProject* ProjectSerializer::hierProject()
{
	assert(m_project != null);
	assert(m_project->getType() == eHierProject);
	DesHierProject* hierProject = dynamic_cast<DesHierProject*>(m_project);
	
	if (hierProject == null)
	{		  
		throw EX("The project beeing loaded is not a HISC project");
	}

	return hierProject;
}

//_________________________________________________________________________________________________

HierSerializerAccess* ProjectSerializer::hierProjAccess()
{
	assert(m_projectAccess != null);
	assert(m_project->getType() == eHierProject);
	
	HierSerializerAccess* hierAccess = dynamic_cast<HierSerializerAccess*>(m_projectAccess);	
	if (hierAccess == null)
	{
		throw EX("The project being loaded does not provide serializer with HISC access");
	}
	
	return hierAccess;
}

//_________________________________________________________________________________________________

bool ProjectSerializer::isHeaderTag(const QString& tagName)
{
	return ((tagName == cProjHeaderTag) || (tagName == cProjIntegrityTag) || (tagName == cProjNonBlockTag) ||
		    (tagName == cProjCtrlTag) || (tagName == cProjIConsTag) || (tagName == cProjLwNonBlockTag) ||
			(tagName == cProjLwCtrlTag));
}

//_________________________________________________________________________________________________
//modified by bini
bool ProjectSerializer::isSubsystemTag(const QString& tagName)
{
	return ((tagName == cSubsysTag) || (tagName == cSubsysImplTag) || (tagName == cSubsysSupDesTag) ||
		(tagName == cSubsysPlantDesTag) ||(tagName == cSubsysTemplateDesTag)|| (tagName == cSubsysUsesTag) || (tagName == cInterfRefTag));
}

//_________________________________________________________________________________________________

bool ProjectSerializer::isInterfaceTag(const QString& tagName)
{
	return ((tagName == cInterfaceTag) || (tagName == cInterfParentTag));
}

//________________________________________________________________________________________________

bool ProjectSerializer::isDesTag(const QString& tagName)
{
	return (tagName == cDesTag);
}
//________________________________________________________________________________________________
//add by bini
bool ProjectSerializer::isInterfaceTemplateDesTag(const QString& tagName)
{
	return (tagName == cInterfaceTemplateDesTag);
}


//_________________________________________________________________________________________________

bool ProjectSerializer::readProjectRoot(const QString& /*tagName*/, const QXmlAttributes& atts)
{
	m_projFileVer = atts.value(cProjFileVerAttr);
	if (m_projFileVer > cProjFileVerVal)
	{
		//the file version is greater than the one supported by this serializer
		qWarning("Des file version (%s) is greater than the one supported (%s). The loading may fail.",
                                 m_projFileVer.toAscii().data(), cProjFileVerVal.toAscii().data());
	}

	return true;
}

//_________________________________________________________________________________________________

bool ProjectSerializer::readProjectDefinition(const QString& tagName, const QXmlAttributes& atts)
{
	if (isHeaderTag(tagName))
	{
		return readProjectHeader(tagName, atts);
	}
	else if (isSubsystemTag(tagName))
	{
		return readSubsystem(tagName, atts);
	}
	
	else if (isInterfaceTag(tagName))
	{
		return readInterface(tagName, atts);
	}
	
	else if (isInterfaceTemplateDesTag(tagName))
	{
		m_readingDesType = eInterfaceTemplateDes;
		
	}
	else if (isDesTag(tagName))
	{
		return readDes(tagName, atts);
	}
//add by bini	
	else if (isParameterTag(tagName))
	{
		return readParameter(tagName,atts);
	}
	else if(isInstantiationTag(tagName))
	{
		m_parameter = new TemplateNameParser::TemplateParameter; 
		//std::vector<std::wstring> m_input;
		m_input.clear();
		return readInstantiation(tagName,atts);
	}
	else
	{
		assert(true);
		qWarning("Unknown tag \"%s\". Tag will be ingored", tagName.toAscii().data());	
		return true;
	}
}

//_________________________________________________________________________________________________

bool ProjectSerializer::readProjectHeader(const QString& tagName, const QXmlAttributes& atts)
{
	if (tagName == cProjHeaderTag)
	{
		//read the name of the project
		QString projName = atts.value(cProjNameAttr);

		//read the type of the project
		QString projTypeName = atts.value(cProjTypeAttr);
		ProjectType projType = getProjectType(projTypeName);
		
		createProject(projType, projName);
	}
	else if (tagName == cProjIntegrityTag)
	{
		//read the integrity status ...
		QString integStatusName = atts.value(cProjIntegStatusAttr);
		m_integStatus = getProjIntegrity(integStatusName);

		//... and the time stamp for the integrity check
		QString integTimeStamp = atts.value(cProjIntegStampAttr);
		m_integDateStamp = integTimeStamp.toStdWString();
	}
	else if (tagName == cProjNonBlockTag)
	{
		//read the non-blocking property and date stamp
		QString nonBlockPropName = atts.value(cProjNonBlockStatusAttr);
		m_nonBlockStatus = getNonBlockProp(nonBlockPropName);

		QString nonBlockStamp = atts.value(cProjNonBlockStampAttr);
		m_nonBlockDateStamp = nonBlockStamp.toStdWString();
	}
	else if (tagName == cProjCtrlTag)
	{
		//read the controllable property and date stamp
		QString ctrlPropName = atts.value(cProjCtrlStatusAttr);
		m_ctrlStatus = getCtrlProp(ctrlPropName);

		QString ctrlStamp = atts.value(cProjCtrlStampAttr);
		m_ctrlDateStamp = ctrlStamp.toStdWString();
	}
	else if (tagName == cProjIConsTag)
	{
		//read the controllable property and date stamp
		QString iConsPropName = atts.value(cProjIConsStatusAttr);
		m_iConsStatus = getProjIConsist(iConsPropName);

		QString iConsStamp = atts.value(cProjIConsStampAttr);
		m_iConsDateStamp = iConsStamp.toStdWString();
	}
	else if (tagName == cProjLwNonBlockTag)
	{
		//read the non-blocking property and date stamp
		QString lwNonBlockPropName = atts.value(cProjLwNonBlockStatusAttr);
		m_lwNonBlockStatus = getLwNonBlockProp(lwNonBlockPropName);

		QString lwNonBlockStamp = atts.value(cProjLwNonBlockStampAttr);
		m_lwNonBlockDateStamp = lwNonBlockStamp.toStdWString();
	}
	else if (tagName == cProjLwCtrlTag)
	{
		//read the controllable property and date stamp
		QString lwCtrlPropName = atts.value(cProjLwCtrlStatusAttr);
		m_lwCtrlStatus = getLwCtrlProp(lwCtrlPropName);

		QString lwCtrlStamp = atts.value(cProjLwCtrlStampAttr);
		m_lwCtrlDateStamp = lwCtrlStamp.toStdWString();
	}
	else
	{
		assert(true);
		qWarning("Unknown tag \"%s\". Tag will be ingored", tagName.toAscii().data());		
	}

	return true;
}

//_________________________________________________________________________________________________

bool ProjectSerializer::readSubsystem(const QString& tagName, const QXmlAttributes& atts)
{
	if (tagName == cSubsysTag) 
	{
		if (m_project->getType() == eHierProject)
		{
			//create the subsystem and read its properties
			QString subsysName = atts.value(cSubsysNameAttr);
			m_crtSubsys = new DesSubsystem(subsysName.toStdWString(), m_projectAccess->getEventPool());
			m_crtSubsys->setLoadInProgress();

			int level = atts.value(cSubsysLevelAttr).toInt();
			m_crtSubsys->setLevel(level);

			QString validName = atts.value(cSubsysValidStatusAttr);
			m_crtSubsys->setValid(getSubsysValidStatus(validName));

			QString lwNonBlockName = atts.value(cSubsysLwNonBlockProp);
			m_crtSubsys->setNonBlocking(getSubsysLwNonBlockProp(lwNonBlockName));

			QString lwCtrlName = atts.value(cSubsysLwCtrlProp);
			m_crtSubsys->setControllable(getSubsysLwCtrlProp(lwCtrlName));

			QString lwIConsistName = atts.value(cSubsysIConsistProp);
			m_crtSubsys->setInterfConsist(getSubsysIConsistProp(lwIConsistName));

			if (m_crtSubsys->isRoot())
			{
				hierProjAccess()->addHighLevelSubsys(m_crtSubsys);
			}
			else
			{
				hierProjAccess()->addLowLevelSubsys(m_crtSubsys);
			}
		}
		else
		{
			//flat project the subsystem has already been created just access it
			m_crtSubsys = &(m_project->getRootSubsys());
			m_crtSubsys->setLoadInProgress();
		}
	}
	else if (tagName == cSubsysSupDesTag)
	{
		m_readingDesType = eSubsysSupDes;
	}
	else if (tagName == cSubsysPlantDesTag)
	{
		m_readingDesType = eSubsysPlantDes;
	}
//add by bini
	else if (tagName == cSubsysTemplateDesTag)
	{
		m_readingDesType = eSubsysTemplateDes;
	}
	

	else if (tagName == cSubsysImplTag) 
	{
		assert(m_project->getType() == eHierProject);
		m_readingInterfRefType = eImplInterface;
	}
	else if (tagName == cSubsysUsesTag)
	{
		assert(m_project->getType() == eHierProject);
		m_readingInterfRefType = eUsesInterface;
	}
	else if (tagName == cInterfRefTag)
	{
		assert(m_project->getType() == eHierProject);
		
		std::wstring interfName = atts.value(cInterfNameAttr).toStdWString();
		
		switch(m_readingInterfRefType)
		{
			case eImplInterface:
				m_unresImpls.push_back(InterfImpl(m_crtSubsys, interfName));
				break;

			case eUsesInterface:
			{	
				std::wstring interfProvider = atts.value(cInterfProviderAttr).toStdWString();
				m_unresDepends.push_back(SubsysDependency(m_crtSubsys, DesSubsystem::DependencyRef(interfName, interfProvider)));
				break;
			}

			default:
				assert(false); //unknown
				qWarning("Unknown interface reference type for tag \"%s\". Tag will be ingored", tagName.toAscii().data());		
		}
	}
	else
	{
		assert(true);
		qWarning("Unknown tag \"%s\". Tag will be ingored", tagName.toAscii().data());		
	}

	return true;
}

//_________________________________________________________________________________________________

bool ProjectSerializer::readInterface(const QString& tagName, const QXmlAttributes& atts)
{
	assert(m_project->getType() == eHierProject);
	
	if (tagName == cInterfaceTag)
	{
		QString interfName = atts.value(cInterfNameAttr);		
		m_crtInterf = new DesInterface(interfName.toStdWString(),m_projectAccess->getEventPool());
		m_crtInterf->setLoadInProgress();

		QString validName = atts.value(cInterfValidStatusAttr);
		m_crtInterf->setValid(getInterfValidStatus(validName));

		QString lwIConsistName = atts.value(cInterfIConsistProp);
		m_crtInterf->setInterfConsist(getInterfIConsistProp(lwIConsistName));

		hierProjAccess()->addInterface(m_crtInterf);

		m_readingDesType = ProjectSerializer::eInterfaceDes;
	}
	else if(tagName == cInterfParentTag)
	{
		std::wstring parentName = atts.value(cInterfParentNameAttr).toStdWString();
		m_unresParent.push_back(InterfParent(m_crtInterf, parentName));
	}
	
	else
	{
		assert(true);
		qWarning("Unknown tag \"%s\". Tag will be ingored", tagName.toAscii().data());		
	}
	
	return true;
}


//_________________________________________________________________________________________________
bool ProjectSerializer::readDes(const QString& tagName, const QXmlAttributes& atts)
{
	if (tagName == cDesTag)
	{
		//obtain the DES information and create a DES
		QString desName = atts.value(cDesNameAttr);
		QString desFileName = convertToAbsolute(atts.value(cDesLocationAttr));
		Des* des = new Des(desName.toStdWString(), desFileName.toStdWString(), true/*delay load*/); 

		//TODO: Before adding the des to the project we need to load it since the project will need
		//to update the project event pool. Delay loading needs a background thread mechanism that
		//loads DES in the background and updates the project event pool synchronized with the projec UI
		//such as not to allow any action until all DES have been loaded
		try
		{
			//make sure this is not a new DES. If you save the project with new DES but don't save DES
			//you get a name but not a file. No point in trying to load nothing
			if (desFileName.isEmpty() == false)
			{
				des->load();
			}
		}
		catch(...)
		{
			qWarning("Errors loading DES \"%s\" from file \"%s\". DES will be ignored.", desName.toAscii().data(), desFileName.toAscii().data());		
			return true; //continue loading
		}

		//add it to the proper container
		switch(m_readingDesType)
		{
			case eSubsysSupDes:
				if (des->isNew())
				{
					//this DES is not comming from a file so we can assume the right type
					des->setType(DESpot::eSubsystemDes);
				}
				
				//add the DES to the project; depending on the type of project this is done a differently. It is
				//important to go through the project and not directly to the subsystem because the project will index
				//the names and will fire notifications
				if (m_project->getType() == eFlatProject)
				{
					flatProject()->addSupDes(des);
				}
				else
				{
					hierProject()->addDes(des, *m_crtSubsys, DESpot::eSupervisorDes);
				}
				break;

			case eSubsysPlantDes:
				if (des->isNew())
				{
					//this DES is not comming from a file so we can assume the right type
					des->setType(DESpot::eSubsystemDes);
				}

				//add the DES to the project; depending on the type of project this is done a differently. It is
				//important to go through the project and not directly to the subsystem because the project will index
				//the names and will fire notifications
				if (m_project->getType() == eFlatProject)
				{
					flatProject()->addPlantDes(des);
				}
				else
				{
					hierProject()->addDes(des, *m_crtSubsys, ePlantDes);
				}
				break;
//add by bini
			case eSubsysTemplateDes:
				m_des=des;
				if (des->isNew())
				{
					//this DES is not comming from a file so we can assume the right type
					des->setType(DESpot::eSubsystemDes);
				}

				//add the DES to the project; depending on the type of project this is done a differently. It is
				//important to go through the project and not directly to the subsystem because the project will index
				//the names and will fire notifications
				if (m_project->getType() == eFlatProject)
				{
					//QString type=atts.value(cSubsysTemplateTypeAttr);
					//char *ch;
					//ch=type.toLatin1().data();
					
					//	if(*ch=='P')
					//	{
					//		des->setLevel(ePlantDes);
					//	}
					//	else if(*ch=='S')
					//	{
					//		des->setLevel(eSupervisorDes);
					//	}
					//	else
					//	{
					//		assert(false);
					//	}
		
					flatProject()->addTemplateDes(des);
				}
	
				else
				{
					/*QString type=atts.value(cSubsysTemplateTypeAttr);
					char *ch;
					ch=type.toLatin1().data();
					
						if(*ch=='P')
						{
							des->setLevel(ePlantDes);
						}
						else if(*ch=='S')
						{
							des->setLevel(eSupervisorDes);
						}
						else
						{
							assert(false);
						}*/
		
					hierProject()->addDes(des,*m_crtSubsys,eTemplateDes);
				}
				break;

			case ProjectSerializer::eInterfaceDes:
				if (des->isNew())
				{
					//this DES is not comming from a file so we can assume the right type
					des->setType(DESpot::eInterfaceDes);
				}

				//add the DES to the project. It is important to go through the project and not directly to 
				//the interface because the project will index the names and will fire notifications
				hierProject()->addDes(des, *m_crtInterf,DESpot::eSupervisorDes);
				break;
			
			case ProjectSerializer::eInterfaceTemplateDes:
				m_des=des;
				if (des->isNew())
				{
					//this DES is not comming from a file so we can assume the right type
					des->setType(DESpot::eInterfaceTemplateDes);
				}

				//add the DES to the project. It is important to go through the project and not directly to 
				//the interface because the project will index the names and will fire notifications
				hierProject()->addDes(des, *m_crtInterf,DESpot::eTemplateDes);
				break;

                        case ProjectSerializer::eNone:
                                assert(true);
                                qWarning("Reading des without a type");
                                break;

		}
	}
	else
	{
		assert(true);
		qWarning("Unknown tag \"%s\". Tag will be ingored", tagName.toAscii().data());		
	}

	return true;
}

//_________________________________________________________________________________________________

/*void ProjectSerializer::writeProjDefinition(XmlWriter& xw)
{
	//The definition contains the project structure: header, subsystems and interfaces
	writeProjHeader(xw);
	
	//write the root subsystem first
	writeSubsystem(xw, m_project->getRootSubsys());
	
	if (m_project->getType() == eHierProject)
	{
		writeProjInterfaces(xw);
	}
*/
//	writeProjSubsystems(xw, false /*exclude root subsystem*/);
//}
//_________________________________________________________________________________________________

void ProjectSerializer::writeProjDefinition(XmlWriter& xw)
{
	//The definition contains the project structure: header, subsystems and interfaces
	writeProjHeader(xw);
	
	if (m_project->getType() == eHierProject)
	{
		writeHierProjDefinition(xw,&(m_project->getRootSubsys()));
	}
	else
	{	//write the root subsystem first
	writeSubsystem(xw, m_project->getRootSubsys());
	
	writeProjSubsystems(xw, false /*exclude root subsystem*/);
	}
	
}

void ProjectSerializer::writeHierProjDefinition(XmlWriter& xw,const DesSubsystem* psubsys)
{
	QList<const DesSubsystem*> que;
	que.append(psubsys);

	 while(!que.empty())
	 {
		 const DesSubsystem* firstSubsys = que.takeFirst();
		 writeSubsystem(xw, *firstSubsys);

		 DesHierProject::InterfIteratorPtr interfIt = hierProject()->createInterfIterator();
		 for(interfIt->first(); interfIt->notDone(); interfIt->next())
		{
		const DesInterface& interf = interfIt->currentItem();
		if(&(interf.getSubsystem()) == firstSubsys)
		{
			writeInterface(xw, interf);
			
			DesHierProject::SubsysIteratorPtr subsysIt = hierProject()->createSubsysIterator();
			for(subsysIt->first(); subsysIt->notDone(); subsysIt->next())
				{
				const DesSubsystem* p_subsys = &(subsysIt->currentItem());
			
				if (&(p_subsys->getInterface())==&interf)
					{
					//std::wstring names=(subsysIt->currentItem()).getName();
					que.append(p_subsys);
					
					}//if ends
				}// for subsys ends
		}	//if ends for interface
		}//for interface ends
		
	 }//while ends	
	
}
//_________________________________________________________________________________________________

void ProjectSerializer::writeProjHeader(XmlWriter& xw)
{
	AttrMap headerAttrs(cProjNameAttr, toString(m_project->getName()),
						cProjTypeAttr, getProjectType());
	
	if (m_project->getType() == eHierProject)
	{
		headerAttrs.add(cProjDegreeAttr, toString(hierProject()->getDegree()));
	}
	
	xw.writeOpenTag(cProjHeaderTag, headerAttrs);

	xw.writeAtomTag(cProjIntegrityTag, AttrMap(cProjIntegStatusAttr, getProjIntegrity(), 
											   cProjIntegStampAttr, toString(m_project->getIntegrityStamp())));
	
	xw.writeAtomTag(cProjNonBlockTag, AttrMap(cProjNonBlockStatusAttr, getNonBlockProp(), 
											  cProjNonBlockStampAttr, toString(m_project->getNonBlockingStamp())));

	xw.writeAtomTag(cProjCtrlTag, AttrMap(cProjCtrlStatusAttr, getCtrlProp(), 
									      cProjCtrlStampAttr, toString(m_project->getCtrlStamp())));

	if (m_project->getType() == eHierProject)
	{
		xw.writeAtomTag(cProjIConsTag, AttrMap(cProjIConsStatusAttr, getProjIConsist(), 
											   cProjIConsStampAttr, toString(hierProject()->getIConsistStamp())));
		
		xw.writeAtomTag(cProjLwNonBlockTag, AttrMap(cProjLwNonBlockStatusAttr, getLwNonBlockProp(), 
												  cProjLwNonBlockStampAttr, toString(hierProject()->getLwNonBlockStamp())));

		xw.writeAtomTag(cProjLwCtrlTag, AttrMap(cProjLwCtrlStatusAttr, getLwCtrlProp(), 
											  cProjLwCtrlStampAttr, toString(hierProject()->getLwCtrlStamp())));
	}

	xw.writeCloseTag(cProjHeaderTag);
}

//_________________________________________________________________________________________________

void ProjectSerializer::writeProjSubsystems(XmlWriter& xw, bool includeRoot)
{
	if (includeRoot)
	{
		//save the root subsystem
		DesSubsystem& rootSubsys = m_project->getRootSubsys();
		writeSubsystem(xw, rootSubsys);
	}

	//if the project is HISC save all other subsystems
	if (m_project->getType() == eHierProject)
	{
		DesHierProject::SubsysIteratorPtr subsysIt = hierProject()->createSubsysIterator();
		for(subsysIt->first(); subsysIt->notDone(); subsysIt->next())
		{
			const DesSubsystem& subsys = subsysIt->currentItem();
			
			if (subsys.isRoot() == false)
			{
				writeSubsystem(xw, subsys);
			}
		}
	}
}

//_________________________________________________________________________________________________

void ProjectSerializer::writeSubsystem(XmlWriter& xw, const DesSubsystem& subsys)
{
	//Write the opening subsystem tag: 
	//e.g. <Subsystem name = "High Level Subsystem" level="0" lw-ctrl ="yes" lw-non-blocking ="yes" i-consist ="yes">
	AttrMap subsysAttrMap(cSubsysNameAttr, toString(subsys.getName()));
	if (m_project->getType() == eHierProject)
	{
		subsysAttrMap.add(cSubsysLevelAttr, getLevelValue(subsys));
		subsysAttrMap.add(cSubsysValidStatusAttr, getSubsysValidStatus(subsys));
		subsysAttrMap.add(cSubsysLwCtrlProp, getSubsysLwCtrlProp(subsys));
		subsysAttrMap.add(cSubsysLwNonBlockProp, getSubsysLwNonBlockProp(subsys));
		subsysAttrMap.add(cSubsysIConsistProp, getSubsysIConsistProp(subsys));
	}
	xw.writeOpenTag(cSubsysTag, subsysAttrMap);
	{		                                
		if (m_project->getType() == eHierProject)
		{
			//write the implements tag with the interface the subsystem implements
			//the root subsystem doesn't implement any interface
			{	
				if (subsys.implementsInterface())
				{
					xw.writeOpenTag(cSubsysImplTag);
					{
						const DesInterface& interf = subsys.getInterface();
						xw.writeAtomTag(cInterfRefTag, AttrMap(cInterfNameAttr, toString(interf.getName())));
					}
					xw.writeCloseTag(cSubsysImplTag);
				}
				else
				{
					//write an empty implementation tag
					xw.writeAtomTag(cSubsysImplTag);
				}
			}
		}

		//write the list of supervisor DES
		xw.writeOpenTag(cSubsysSupDesTag);
		{
			DesSubsystem::DesIteratorPtr desIt = subsys.createDesIterator(eSupervisorDes);
			for(desIt->first(); desIt->notDone(); desIt->next())
			{
				const Des& des = desIt->currentItem();
				if(des.isInstantiation()==false)
				{	
					xw.writeAtomTag(cDesTag, AttrMap(cDesNameAttr, toString(des.getName()),
								cDesLocationAttr, convertToRelative(toString(des.getFileName()))));
				}			
			}
		}
		xw.writeCloseTag(cSubsysSupDesTag);

		//write the list of plant DES
		xw.writeOpenTag(cSubsysPlantDesTag);
		{
			DesSubsystem::DesIteratorPtr desIt = subsys.createDesIterator(ePlantDes);
			for(desIt->first(); desIt->notDone(); desIt->next())
			{
				const Des& des = desIt->currentItem();
				if(des.isInstantiation()==false)
				{			
					xw.writeAtomTag(cDesTag, AttrMap(cDesNameAttr, toString(des.getName()),cDesLocationAttr, convertToRelative(toString(des.getFileName()))));

				}
			}
		}
		xw.writeCloseTag(cSubsysPlantDesTag);
//add by bini
		//write the list of template DES
		xw.writeOpenTag(cSubsysTemplateDesTag);
		{
			DesSubsystem::DesIteratorPtr desIt = subsys.createDesIterator(eTemplateDes);
			for(desIt->first(); desIt->notDone(); desIt->next())
			{
				const Des& des = desIt->currentItem();
				xw.writeOpenTag(cDesTag,AttrMap(cDesNameAttr,toString(des.getName()),	cDesLocationAttr,convertToRelative((toString(des.getFileName())))));
				if(des.isInstantiated())
				{
					DesSubsystem::InstIteratorPtr InstIt = subsys.createInstIterator();
					for(InstIt->first();InstIt->notDone();InstIt->next())
					{
						Instantiation& inst=InstIt->currentItem();
						if(&des==inst.getTemplateDes())
						{
							xw.writeOpenTag(cInstantiationTag,AttrMap(cInstInfoDlgNameAttr,toString(inst.getName()),cSubsysTemplateTypeAttr,getTypeVal(inst.getLevel()),cInstantiationInputType,getInputType(inst.getInputType())));
							TemplateNameParser::TemplateParameterItr itr=inst.getParameter()->begin();
							if(inst.getInputType()==eRange)
							{
								while(itr!=inst.getParameter()->end())
								{
									xw.writeAtomTag(cTemplateParameterTag,AttrMap(cTemplateParameterNameAttr,toString(itr->first),cTemplateParameterValueAttr,toString(itr->second)));
									itr++;
								}
								
							}
							if(inst.getInputType()==eTuple)
							{
								QString tuplename;
								tuplename.append("(");
								while(itr!=inst.getParameter()->end())
								{
									tuplename.append(QString::fromStdWString(itr->first));
									itr++;
									if(itr!=inst.getParameter()->end())
									{
										tuplename.append(",");
									}
								}
								tuplename.append(")");
								xw.writeAtomTag(cTemplateParameterTag,AttrMap(cTemplateParameterNameAttr,tuplename,cTemplateParameterValueAttr,QString::fromStdWString(inst.getTupleInput())));
							}
							xw.writeCloseTag(cInstantiationTag);
						}
					}
				}
				xw.writeCloseTag(cDesTag);
			}
		}
		xw.writeCloseTag(cSubsysTemplateDesTag);

		if (m_project->getType() == eHierProject)
		{
			//write the list of dependent subsystems
			if (subsys.getDependsCount() != 0)
			{
				xw.writeOpenTag(cSubsysUsesTag);
				{
					//<InterfaceRef name = "Interface 1" provider ="Low Level Subsystem 1"/>
					DesSubsystem::DependIteratorPtr depIt = subsys.createDependsIterator();
					for(depIt->first(); depIt->notDone(); depIt->next())
					{
						const DesSubsystem::Dependency& depend = depIt->currentItem();
						xw.writeAtomTag(cInterfRefTag, AttrMap(cInterfNameAttr, toString(depend.interface->getName()),
										cInterfProviderAttr, toString(depend.subsystem->getName())));
						
					}			
				}
				xw.writeCloseTag(cSubsysUsesTag);
			}
			else
			{
				xw.writeAtomTag(cSubsysUsesTag);
			}
		}
	}






	xw.writeCloseTag(cSubsysTag);
}

//_________________________________________________________________________________________________

void ProjectSerializer::writeProjInterfaces(XmlWriter& xw)
{
	DesHierProject::InterfIteratorPtr interfIt = hierProject()->createInterfIterator();
	for(interfIt->first(); interfIt->notDone(); interfIt->next())
	{
		const DesInterface& interf = interfIt->currentItem();
		writeInterface(xw, interf);
	}
}

//_________________________________________________________________________________________________

void ProjectSerializer::writeInterface(XmlWriter& xw, const DesInterface& interf)
{
	//Write the interface tag: e.g. <Interface name = "Interface 1">
	xw.writeOpenTag(cInterfaceTag, AttrMap(cInterfNameAttr, toString(interf.getName()),
										   cInterfValidStatusAttr, getInterfValidStatus(interf),
										   cInterfIConsistProp, getInterfIConsistProp(interf)));
	{
		//write the Parent Subsystem for this interface
		xw.writeAtomTag(cInterfParentTag, AttrMap(cDesNameAttr, toString(interf.getSubsystem().getName())));

		//write all DES that are part of the interface
		//e.g. <Des name = "I1-Des-1" location="FullPath\I1-Des-1.des"/>
		DesInterface::DesIteratorPtr desIt = interf.createDesIterator();
		for(desIt->first(); desIt->notDone(); desIt->next())
		{
			const Des& des = desIt->currentItem();
			if(des.isInstantiation()==false)
			{
				xw.writeAtomTag(cDesTag, AttrMap(cDesNameAttr, toString(des.getName()),
											 cDesLocationAttr, convertToRelative(toString(des.getFileName()))));
			}
		}

		xw.writeOpenTag(cInterfaceTemplateDesTag);
		DesInterface::DesIteratorPtr desIt2 = interf.createDesIterator(eTemplateDes);
		for(desIt2->first(); desIt2->notDone(); desIt2->next())
		{
			const Des& des2 = desIt2->currentItem();
			xw.writeAtomTag(cDesTag, AttrMap(cDesNameAttr, toString(des2.getName()),
											 cDesLocationAttr, convertToRelative(toString(des2.getFileName()))));
			if(des2.isInstantiated())
				{
					DesInterface::InstIteratorPtr InstIt = interf.createInstIterator();
					for(InstIt->first();InstIt->notDone();InstIt->next())
					{
						Instantiation& inst=InstIt->currentItem();
						if(&des2==inst.getTemplateDes())
						{
							xw.writeOpenTag(cInstantiationTag,AttrMap(cInstInfoDlgNameAttr,toString(inst.getName()),cSubsysTemplateTypeAttr,getTypeVal(inst.getLevel()),cInstantiationInputType,getInputType(inst.getInputType())));
						TemplateNameParser::TemplateParameterItr itr=inst.getParameter()->begin();

						if(inst.getInputType()==eRange)
							{
								while(itr!=inst.getParameter()->end())
								{
									xw.writeAtomTag(cTemplateParameterTag,AttrMap(cTemplateParameterNameAttr,toString(itr->first),cTemplateParameterValueAttr,toString(itr->second)));
									itr++;
								}
								
							}
							if(inst.getInputType()==eTuple)
							{
								QString tuplename;
								tuplename.append("(");
								while(itr!=inst.getParameter()->end())
								{
									tuplename.append(QString::fromStdWString(itr->first));
									itr++;
									if(itr!=inst.getParameter()->end())
									{
										tuplename.append(",");
									}
								}
								tuplename.append(")");
								xw.writeAtomTag(cTemplateParameterTag,AttrMap(cTemplateParameterNameAttr,tuplename,cTemplateParameterValueAttr,QString::fromStdWString(inst.getTupleInput())));
							}
						xw.writeCloseTag(cInstantiationTag);
						}
					}
				}
		}
		xw.writeCloseTag(cInterfaceTemplateDesTag);
		
		
	}
	xw.writeCloseTag(cInterfaceTag);
}

//_________________________________________________________________________________________________

ProjectType ProjectSerializer::getProjectType(const QString& projTypeName)
{
	if (projTypeName == cProjTypeFlatVal)
	{
		return eFlatProject;
	}
	else if (projTypeName == cProjTypeHierVal)
	{
		return eHierProject;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to flat project", projTypeName.toAscii().data());		
		return eFlatProject;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getProjectType()
{
	switch(m_project->getType())
	{
		case eFlatProject:
			return cProjTypeFlatVal;

		case eHierProject:
			return cProjTypeHierVal;

		default:
			assert(true);
			qWarning("Unknown project type value.");		
			return "ERROR: Unknown project type";
	}
}

//_________________________________________________________________________________________________

Integrity ProjectSerializer::getProjIntegrity(const QString& integStatusName)
{
	if (integStatusName == cProjIntegStatusYesVal)
	{
		return eIntegYes;
	}
	else if (integStatusName == cProjIntegStatusNoVal)
	{
		return eIntegNo;
	}
	else if ( integStatusName == cProjIntegStatusNotVerifVal)
	{
		return eIntegNotVerified;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to integrity-not-verified", integStatusName.toAscii().data());		
		return eIntegNotVerified;
	}
}

//_________________________________________________________________________________________________

QString	ProjectSerializer::getProjIntegrity()
{
	switch(m_project->getIntegrity())
	{
		case eIntegYes:
			return cProjIntegStatusYesVal;

		case eIntegNo:
			return cProjIntegStatusNoVal;

		case eIntegNotVerified:
			return cProjIntegStatusNotVerifVal;

		default:
			assert(true);
			qWarning("Unknown project integrity value.");		
			return "ERROR: Unknown integrity value";
	}
}

//_________________________________________________________________________________________________

ControllableProp ProjectSerializer::getCtrlProp(const QString& ctrlPropName)
{
	if (ctrlPropName == cProjCtrlPropYesVal)
	{
		return eCtrlYes;
	}
	else if (ctrlPropName == cProjCtrlPropNoVal)
	{
		return eCtrlNo;
	}
	else if ( ctrlPropName == cProjCtrlPropNotVerifVal)
	{
		return eCtrlNotVerified;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to not-verified", ctrlPropName.toAscii().data());		
		return eCtrlNotVerified;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getCtrlProp()
{
	switch(m_project->getControllableProp())
	{
		case eCtrlYes:
			return cProjCtrlPropYesVal;

		case eCtrlNo:
			return cProjCtrlPropNoVal;

		case eCtrlNotVerified:
			return cProjCtrlPropNotVerifVal;

		default:
			assert(true);
			qWarning("Unknown project controllable property value.");		
			return "ERROR: Unknown controllable property value";
	}
}

//_________________________________________________________________________________________________

NonBlockingProp ProjectSerializer::getNonBlockProp(const QString& nonBlockPropName)
{
	if (nonBlockPropName == cProjNonBlockPropYesVal)
	{
		return eNonBlockYes;
	}
	else if (nonBlockPropName == cProjNonBlockPropNoVal)
	{
		return eNonBlockNo;
	}
	else if ( nonBlockPropName == cProjNonBlockPropNotVerifVal)
	{
		return eNonBlockNotVerified;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to not-verified", nonBlockPropName.toAscii().data());		
		return eNonBlockNotVerified;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getNonBlockProp()
{
	switch(m_project->getNonBlockingProp())
	{
		case eNonBlockYes:
			return cProjNonBlockPropYesVal;

		case eNonBlockNo:
			return cProjNonBlockPropNoVal;

		case eNonBlockNotVerified:
			return cProjNonBlockPropNotVerifVal;

		default:
			assert(true);
			qWarning("Unknown value nonblocking property value");		
			return "ERROR: Unknown non-blocking value";
	}
}

//_________________________________________________________________________________________________

IConsistProp ProjectSerializer::getProjIConsist(const QString& iConsName)
{
	if (iConsName == cProjIConsPropYesVal)
	{
		return eIConsYes;
	}
	else if (iConsName == cProjIConsPropNoVal)
	{
		return eIConsNo;
	}
	else if ( iConsName == cProjIConsPropNotVerifVal)
	{
		return eIConsNotVerified;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to integrity-not-verified", iConsName.toAscii().data());		
		return eIConsNotVerified;
	}
}

//_________________________________________________________________________________________________

QString	ProjectSerializer::getProjIConsist()
{
	switch(hierProject()->getIConsistProp())
	{
		case eIConsYes:
			return cProjIConsPropYesVal;

		case eIConsNo:
			return cProjIConsPropNoVal;

		case eIConsNotVerified:
			return cProjIConsPropNotVerifVal;

		default:
			assert(true);
			qWarning("Unknown interface consistent property value.");		
			return "ERROR: Unknown interface consistent property value";
	}
}

//_________________________________________________________________________________________________

LwCtrlProp ProjectSerializer::getLwCtrlProp(const QString& lwCtrlPropName)
{
	if (lwCtrlPropName == cProjLwCtrlPropYesVal)
	{
		return eLwCtrlYes;
	}
	else if (lwCtrlPropName == cProjLwCtrlPropNoVal)
	{
		return eLwCtrlNo;
	}
	else if ( lwCtrlPropName == cProjLwCtrlPropNotVerifVal)
	{
		return eLwCtrlNotVerified;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to not-verified", lwCtrlPropName.toAscii().data());		
		return eLwCtrlNotVerified;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getLwCtrlProp()
{
	switch(hierProject()->getLwCtrlProp())
	{
		case eLwCtrlYes:
			return cProjLwCtrlPropYesVal;

		case eLwCtrlNo:
			return cProjLwCtrlPropNoVal;

		case eLwCtrlNotVerified:
			return cProjLwCtrlPropNotVerifVal;

		default:
			assert(true);
			qWarning("Unknown project LD level-wise controllable property value.");		
			return "ERROR: Unknown LD level-wise controllable property value";
	}
}

//_________________________________________________________________________________________________

LwNonBlockProp ProjectSerializer::getLwNonBlockProp(const QString& lwNonBlockPropName)
{
	if (lwNonBlockPropName == cProjLwNonBlockPropYesVal)
	{
		return eLwNonBlockYes;
	}
	else if (lwNonBlockPropName == cProjLwNonBlockPropNoVal)
	{
		return eLwNonBlockNo;
	}
	else if ( lwNonBlockPropName == cProjLwNonBlockPropNotVerifVal)
	{
		return eLwNonBlockNotVerified;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to not-verified", lwNonBlockPropName.toAscii().data());		
		return eLwNonBlockNotVerified;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getLwNonBlockProp()
{
	switch(hierProject()->getLwNonBlockProp())
	{
		case eLwNonBlockYes:
			return cProjLwNonBlockPropYesVal;

		case eLwNonBlockNo:
			return cProjLwNonBlockPropNoVal;

		case eLwNonBlockNotVerified:
			return cProjLwNonBlockPropNotVerifVal;

		default:
			assert(true);
			qWarning("Unknown value LD level-wise nonblocking property value");		
			return "ERROR: Unknown LD level-wise non-blocking value";
	}
}


//_________________________________________________________________________________________________

QString ProjectSerializer::getLevelValue(const DesSubsystem& subsys)
{
	return QVariant(subsys.getLevel()).toString();
}

//_________________________________________________________________________________________________

bool ProjectSerializer::getSubsysLwCtrlProp(const QString& lwCtrlPropName)
{
	if (lwCtrlPropName == cSubsysLwCtrlYesVal)
	{
		return true;
	}
	else if (lwCtrlPropName == cSubsysLwCtrlNoVal)
	{
		return false;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to -no-", lwCtrlPropName.toAscii().data());		
		return false;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getSubsysLwCtrlProp(const DesSubsystem& subsys)
{
	return subsys.isControllable() ? cSubsysLwCtrlYesVal : cSubsysLwCtrlNoVal;
}

//_________________________________________________________________________________________________

bool ProjectSerializer::getSubsysLwNonBlockProp(const QString& lwNonBlockPropName)
{
	if (lwNonBlockPropName == cSubsysLwNonBlockYesVal)
	{
		return true;
	}
	else if (lwNonBlockPropName == cSubsysLwNonBlockNoVal)
	{
		return false;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to -no-", lwNonBlockPropName.toAscii().data());		
		return false;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getSubsysLwNonBlockProp(const DesSubsystem& subsys)
{
	return subsys.isNonBlocking() ? cSubsysLwNonBlockYesVal : cSubsysLwNonBlockNoVal;
}

//_________________________________________________________________________________________________

bool ProjectSerializer::getSubsysIConsistProp(const QString& iConsistPropName)
{
	if (iConsistPropName == cSubsysIConsistYesVal)
	{
		return true;
	}
	else if (iConsistPropName == cSubsysIConsistNoVal)
	{
		return false;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to -no-", iConsistPropName.toAscii().data());		
		return false;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getSubsysIConsistProp(const DesSubsystem& subsys)
{
	return subsys.isInterfConsist() ? cSubsysIConsistYesVal : cSubsysIConsistNoVal;  
}

//_________________________________________________________________________________________________

bool ProjectSerializer::getInterfIConsistProp(const QString& iConsistPropName)
{
	if (iConsistPropName == cInterfIConsistYesVal)
	{
		return true;
	}
	else if (iConsistPropName == cInterfIConsistNoVal)
	{
		return false;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to -no-", iConsistPropName.toAscii().data());		
		return false;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getInterfIConsistProp(const DesInterface& interf)
{
	return interf.isInterfConsist() ? cInterfIConsistYesVal : cInterfIConsistNoVal;  
}

//_________________________________________________________________________________________________

bool ProjectSerializer::getSubsysValidStatus(const QString& validStatusName)
{
	if (validStatusName == cSubsysValidStatusYesVal)
	{
		return true;
	}
	else if (validStatusName == cSubsysValidStatusNoVal)
	{
		return false;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to -no-", validStatusName.toAscii().data());		
		return false;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getSubsysValidStatus(const DesSubsystem& subsys)
{
	return subsys.isValid() ? cSubsysValidStatusYesVal : cSubsysValidStatusNoVal;  
}

//_________________________________________________________________________________________________

bool ProjectSerializer::getInterfValidStatus(const QString& validStatusName)
{
	if (validStatusName == cInterfValidStatusYesVal)
	{
		return true;
	}
	else if (validStatusName == cInterfValidStatusNoVal)
	{
		return false;
	}
	else
	{
		assert(true);
		qWarning("Unknown value \"%s\". Value will default to -no-", validStatusName.toAscii().data());		
		return false;
	}
}

//_________________________________________________________________________________________________

QString ProjectSerializer::getInterfValidStatus(const DesInterface& interf)
{
	return interf.isValid() ? cInterfValidStatusYesVal : cInterfValidStatusNoVal;  
}

//_________________________________________________________________________________________________

void ProjectSerializer::setProjectProperties()
{
	m_projectAccess->setIntegrity(m_integStatus);
	m_projectAccess->setIntegrityStamp(m_integDateStamp);

	m_projectAccess->setNonBlockingProp(m_nonBlockStatus);
	m_projectAccess->setNonBlockingStamp(m_nonBlockDateStamp);

	m_projectAccess->setControllableProp(m_ctrlStatus);
	m_projectAccess->setCtrlStamp(m_ctrlDateStamp);

	if (m_project->getType() == eHierProject)
	{
		hierProjAccess()->setIConsistProp(m_iConsStatus);
		hierProjAccess()->setIConsistStamp(m_iConsDateStamp);

		hierProjAccess()->setLwNonBlockProp(m_lwNonBlockStatus);
		hierProjAccess()->setLwNonBlockStamp(m_lwNonBlockDateStamp);

		hierProjAccess()->setLwCtrlProp(m_lwCtrlStatus);
		hierProjAccess()->setLwCtrlStamp(m_lwCtrlDateStamp);
	}
}

//_________________________________________________________________________________________________

void ProjectSerializer::resolveInterfImplementations()
{
	for(unsigned int i = 0; i < m_unresImpls.size(); i++)
	{
		InterfImpl& unresImpl = m_unresImpls[i];
		DesInterface* interf = hierProjAccess()->getInterface(unresImpl.interfName);
		unresImpl.subsys->setInterface(*interf);
	}
}

//_________________________________________________________________________________________________

void ProjectSerializer::resolveSubsysDependencies()
{
	for(unsigned int i = 0; i < m_unresDepends.size(); i++)
	{
		SubsysDependency& unresDepend = m_unresDepends[i];
		DesInterface* interf = hierProjAccess()->getInterface(unresDepend.dependRef.interfName);
		DesSubsystem* lSubsys = hierProjAccess()->getSubsystem(unresDepend.dependRef.subsysName);
		unresDepend.subsys->addDependency(interf, lSubsys);
		m_unresParent.push_back(InterfParent(interf, unresDepend.subsys->getName()));
	}
}

//_________________________________________________________________________________________________

void ProjectSerializer::resolveInterfParent()
{
	for(unsigned int i = 0; i < m_unresParent.size(); i++)
	{
		InterfParent& unresParent = m_unresParent[i];
		DesSubsystem* subsys = hierProjAccess()->getSubsystem(unresParent.parentName);
		unresParent.interf->setSubsystem(*subsys);
	}
}
//_________________________________________________________________________________________________

QString ProjectSerializer::toString(int intVal)
{
	return QVariant(intVal).toString();
}

//_________________________________________________________________________________________________

QString ProjectSerializer::toString(const std::wstring stdStr)
{
	return QString::fromStdWString(stdStr);
}

//_________________________________________________________________________________________________

QString ProjectSerializer::convertToRelative(const QString& desFileName)
{
	QFileInfo projFileInfo(m_fileName);
	QDir projDir = projFileInfo.dir();
	return projDir.relativeFilePath(desFileName);
}

//_________________________________________________________________________________________________

QString ProjectSerializer::convertToAbsolute(const QString& desRelativeFileName)
{
	if (desRelativeFileName.isEmpty())
		return QString();

	QFileInfo projFileInfo(m_fileName);
	QDir projDir = projFileInfo.dir();
	return QDir::cleanPath(projDir.absoluteFilePath(desRelativeFileName));
}
//_________________________________________________________________________________________________

void ProjectSerializer::createCloneDes(const std::wstring& containerName,const Des& existingDes, DesType desType,
											const bool isChildInterf, const bool isInterfAboveHigh)
{
	std::wstring desName= existingDes.getName();
	Des* newDes;
	if(desType == eInterfaceDes)
	{
		newDes = new Des(desName);
	}
	else
	{
		newDes = new Des(desName, eSubsystemDes);
	}
	newDes->loadCloneDes(existingDes,changedEventsMap,isChildInterf,isInterfAboveHigh);
	m_unresExtraction.push_back(ExtractionData(containerName,newDes,desType));
		 
}
//_________________________________________________________________________________________________
DesProject* ProjectSerializer::extractionSystem(const DesSubsystem* highLevel)
{
	bool isBilevelExtraction= true;
	bool skipTest = false;
	//Before creating Highlevel get info of rootSubsystem
	std::wstring highLevelName=highLevel->getName();
	// key is InterfaceName and value is SubsystemName
	std::map<std::wstring, std::wstring> subsysInterfMap;
	std::map<std::wstring, std::wstring>::iterator subsysInterfMapIt;
	// key is lowlevel-Subsys name and value is if it is leaf node in original project
	std::map<std::wstring, bool> extractionSkipTestMap;
	std::map<std::wstring, bool>::iterator extractionSkipTestMapIt;
	
	//get and store the des of the highlevel and interface above it if it is not a rootNode in original project 
	if(highLevel->isRoot() == false)
	{
		DesInterface::DesIteratorPtr intAboveDesIt = (highLevel->getInterface()).createDesIterator();
		for(intAboveDesIt->first(); intAboveDesIt->notDone(); intAboveDesIt->next())
		{
		  Des& existingDes = intAboveDesIt->currentItem();
		  createCloneDes(highLevelName,existingDes,eSubsysPlantDes,false,true);
		  }
		skipTest=true;
	}
	else
	{
		skipTest=false;
	}
	DesSubsystem::DesIteratorPtr highSupDesIt = highLevel->createDesIterator(eSupervisorDes);
		for(highSupDesIt->first(); highSupDesIt->notDone(); highSupDesIt->next())
		{
		  Des& existingDes = highSupDesIt->currentItem();
		  createCloneDes(highLevelName,existingDes,eSubsysSupDes,false,false);
		  }
	DesSubsystem::DesIteratorPtr highPlntDesIt = highLevel->createDesIterator(ePlantDes);
		for(highPlntDesIt->first(); highPlntDesIt->notDone(); highPlntDesIt->next())
		{
		  Des& existingDes = highPlntDesIt->currentItem();
		  createCloneDes(highLevelName,existingDes,eSubsysPlantDes,false,false);
		  }

	//get and store the des of the lowlevels and interfaces below highlevel
	DesSubsystem::DependIteratorPtr depIt = highLevel->createDependsIterator();
	for(depIt->first(); depIt->notDone(); depIt->next())
	{
		const DesSubsystem::Dependency& depend = depIt->currentItem();
		DesSubsystem* subsys= depend.subsystem;
		DesInterface* interf= depend.interface;
		std::wstring lowLevelName=subsys->getName();
		subsysInterfMap[depend.interface->getName()]=lowLevelName;
		
		//get and store the des of the interface below lowlevel 
		 DesHierProject::InterfIteratorPtr interfBelowIt = hierProject()->createInterfIterator();
		 for(interfBelowIt->first(); interfBelowIt->notDone(); interfBelowIt->next())
		{
		const DesInterface& interfBelow = interfBelowIt->currentItem();
		if(&(interfBelow.getSubsystem()) == subsys)
			{
				DesInterface::DesIteratorPtr intBelowDesIt = interfBelow.createDesIterator();
				for(intBelowDesIt->first(); intBelowDesIt->notDone(); intBelowDesIt->next())
				{
				 Des& existingDes = intBelowDesIt->currentItem();
				 createCloneDes(lowLevelName,existingDes,eSubsysPlantDes,true,false);
				}
				extractionSkipTestMap[lowLevelName]=true;
			}
		
		}

		DesSubsystem::DesIteratorPtr supdesIt = subsys->createDesIterator(eSupervisorDes);
		for(supdesIt->first(); supdesIt->notDone(); supdesIt->next())
		{
		  Des& existingDes = supdesIt->currentItem();
		  createCloneDes(lowLevelName,existingDes,eSubsysSupDes,false,false);
		}

		DesSubsystem::DesIteratorPtr plntdesIt = subsys->createDesIterator(ePlantDes);
		for(plntdesIt->first(); plntdesIt->notDone(); plntdesIt->next())
		{
		  Des& existingDes = plntdesIt->currentItem();
		  createCloneDes(lowLevelName,existingDes,eSubsysPlantDes,false,false);
		}
		
		DesInterface::DesIteratorPtr intdesIt = interf->createDesIterator();
		for(intdesIt->first(); intdesIt->notDone(); intdesIt->next())
		{
		  Des& existingDes = intdesIt->currentItem();
		  createCloneDes(interf->getName(),existingDes,eInterfaceDes,false,false);
		 }

	}
	//create the extraction Project and add highlevel, interfaces, lowlevels and respective des
		const QString ExtractionProjName = toString(m_project->getName());
		DesProject* originalProj = m_project;
		ProjectType projType = getProjectType("HISC");
		createProject(projType, ExtractionProjName);

		m_crtSubsys = new DesSubsystem(highLevelName, m_projectAccess->getEventPool(),isBilevelExtraction);
		m_crtSubsys->setLoadInProgress();
		m_crtSubsys->setLevel(0);
		m_crtSubsys->setExtractionSystemSkipTest(skipTest); 
		hierProjAccess()->addHighLevelSubsys(m_crtSubsys);
		DesSubsystem* p_highLevl= m_crtSubsys;
		
		for( subsysInterfMapIt = subsysInterfMap.begin(); subsysInterfMapIt != subsysInterfMap.end(); subsysInterfMapIt++ ) 
		{
		m_crtInterf = new DesInterface(subsysInterfMapIt->first,m_projectAccess->getEventPool());
		m_crtInterf->setLoadInProgress();
		hierProjAccess()->addInterface(m_crtInterf);
		m_crtInterf->setSubsystem(*p_highLevl);

		m_crtSubsys = new DesSubsystem(subsysInterfMapIt->second, m_projectAccess->getEventPool(),isBilevelExtraction);
		m_crtSubsys->setLoadInProgress();
		m_crtSubsys->setLevel(1);
		m_crtSubsys->setBilevelExtrationFlag(true);
		hierProjAccess()->addLowLevelSubsys(m_crtSubsys);
		m_crtSubsys->setInterface(*m_crtInterf);
		p_highLevl->addDependency(m_crtInterf, m_crtSubsys);

		//set the extraction non leaf flag to true if the lowlevel has a interface under it
		extractionSkipTestMapIt = extractionSkipTestMap.find(subsysInterfMapIt->second);
			if (extractionSkipTestMapIt == extractionSkipTestMap.end())
			{
				m_crtSubsys->setExtractionSystemSkipTest(false);
			}
			else
			{
				m_crtSubsys->setExtractionSystemSkipTest(true);
			}
		}
		
		for(unsigned int i = 0; i < m_unresExtraction.size(); i++)
		{
			ExtractionData& unresData = m_unresExtraction[i];
			Des* pDes= unresData.p_des;
			switch(unresData.desType)
			{
			case eSubsysSupDes:
			pDes->setType(DESpot::eSubsystemDes);
			hierProject()->addDes(pDes,unresData.container,DESpot::eSupervisorDes);
			break;
			
			case eSubsysPlantDes:
			pDes->setType(DESpot::eSubsystemDes);
			hierProject()->addDes(pDes, unresData.container, ePlantDes);
			break;

			case eInterfaceDes:
			pDes->setType(DESpot::eInterfaceDes);
			hierProject()->addDes(pDes, unresData.container);
			break;

			case ProjectSerializer::eNone:
				assert(true);
				qWarning("Reading des without a type");
				break;
			}
		}
				
		HierProjIntegrityAlgo integAlgo;
		//ProjectEditor::onCheckProjectIntegrity(integAlgo);
		m_project->checkIntegrity(integAlgo);
		if(m_project->isValid()==false)
		{
			originalProj->clean(true);
			throw EX("Either project is not valid, or integrity has not yet been checked.");
			
			//m_projectAccess->setIntegrity(eIntegNo);
			//return null;
		}
		//m_projectAccess->setIntegrity(eIntegYes);
		changedEventsMap.clear();
		return m_project;
		
}
//add by bini
	bool ProjectSerializer::isParameterTag( const QString& tagName )
	{
		return (tagName == cTemplateParameterTag);
	}

	bool ProjectSerializer::isInstantiationTag( const QString& tagName )
	{
		return (tagName == cInstantiationTag);
	}

	bool ProjectSerializer::readParameter( const QString& tagName, const QXmlAttributes& atts )
	{
		if (tagName == cTemplateParameterTag)
		{
			if(m_des->isInstantiated()==false)
			{
				m_des->setParameter(new TemplateNameParser::TemplateParameter);
				m_des->setInstantiated(true);
			}
			//obtain the DES information and create a DES
			QString parName = atts.value(cTemplateParameterNameAttr);
			QString parValue = atts.value(cTemplateParameterValueAttr);
			setTemplateParameter(parName.toStdWString(),parValue.toStdWString());
			setTemplateInput(parValue.toStdWString());
			m_inst->setParameter(getTemplateParameter());
			m_inst->setInput(getTemplateInput());

		}
		return true;
	}
	
	bool ProjectSerializer::readInstantiation( const QString& tagName, const QXmlAttributes& atts )
	{
	
		if (tagName == cInstantiationTag)
		{
			TemplateNameParser::TemplateParameter* temp_par;
			//obtain the DES information and create a DES
			QString insttype = atts.value(cSubsysTemplateTypeAttr);
			QString instname = atts.value(cInstInfoDlgNameAttr);
			QString instinputtype=atts.value(cInstantiationInputType);
			DesLevel deslevel;
           		if (insttype == ProjectSerializer::cSubsysTemplateTypePlantVal)
               		{
				deslevel = ePlantDes;
			}
            		else if(insttype == ProjectSerializer::cSubsysTemplateTypeSupVal)
               		{
				deslevel = eSupervisorDes;
			}
          		InputType inputtype;
           		if (instinputtype == ProjectSerializer::cSubsysInputTypeRangeVal)
               		{
				inputtype = eRange;
			}
           		else if (instinputtype == ProjectSerializer::cSubsysInputTypeTupleVal)
                	{
				inputtype = eTuple;
			}
			//m_des->setLevel(deslevel);
			
			//TemplateNameParser::TemplateParameterItr it=temp_par->begin();
			std::wstring tuple_input;
			std::vector<std::wstring> rangeinput;
			if(inputtype==eRange)
			{	
				//std::vector<std::wstring> rangeinput;
				//rangeinput.push_back(it->second);
           		
            			m_inst = new Instantiation(instname.toStdWString(), deslevel, temp_par, inputtype, m_des, rangeinput, tuple_input);
			}
			if(inputtype==eTuple)
			{
				//std::vector<std::wstring> tupleinput=getTemplateInput();
				
           		
            			m_inst = new Instantiation(instname.toStdWString(), deslevel, temp_par, inputtype, m_des, rangeinput, tuple_input);
			}
			
		}
		return true;
	}
	

QString ProjectSerializer::getTypeVal(const DesLevel& lev)
{
		if(lev==eSupervisorDes)
		{
			return cSubsysTemplateTypeSupVal;
					
		}
		else if(lev==ePlantDes)
		{
			return cSubsysTemplateTypePlantVal;
		}
}

QString ProjectSerializer::getInputType(const InputType& input)
{
	if(input==eRange)
	{
		return cSubsysInputTypeRangeVal;
	}
	else if(input==eTuple)
	{
		return cSubsysInputTypeTupleVal;
	}


}

void ProjectSerializer::setTemplateParameter(wstring parname,wstring parvalue)
{

	if(m_inst->getInputType()==eRange)
	{
		m_parameter->insert(TemplateNameParser::TemplateParameter::value_type(parname,parvalue));
	}
	if(m_inst->getInputType()==eTuple)
	{
		std::vector<std::wstring> name_vector;
		std::vector<std::wstring> value_vector;
		parser_name(parname,name_vector);
		parser_value(parvalue,value_vector);
		std::vector<std::wstring>::iterator it_name=name_vector.begin();
		std::vector<std::wstring>::iterator it_value=value_vector.begin();
		while(it_name!=name_vector.end())
		{
			m_parameter->insert(TemplateNameParser::TemplateParameter::value_type(*it_name,*it_value));
			it_name++;
			it_value++;
		}
	}
}

TemplateNameParser::TemplateParameter* ProjectSerializer::getTemplateParameter()
{
	return m_parameter;
}

void ProjectSerializer::setTemplateInput(std::wstring parvalue)
{
	
	m_input.push_back(parvalue);

}

std::vector<std::wstring> ProjectSerializer::getTemplateInput()
{
	return m_input;
}

void ProjectSerializer::parser_name(std::wstring parname, std::vector<std::wstring> &name_vector)
{
	int i=0;
	int length=parname.size();
	while(i<length)
	{
		if(parname[i]==L'('||parname[i]==L','||parname[i]==L')')
		{
			i++;
		}
		else
		{
			std::wstring temp;
			temp+=parname[i];
			name_vector.push_back(temp);
			i++;
		}
	}
}

void ProjectSerializer::parser_value(std::wstring parvalue,std::vector<std::wstring> &value_vector)
{
	std::vector<std::wstring> tuplevector;
	std::vector<std::vector<std::wstring> > valuevector_vector;
	parseTuple(parvalue,tuplevector);
	parseVector(tuplevector,valuevector_vector);
	for(int j=0;j<valuevector_vector[0].size();j++)
	{
		std::wstring result;
		int i=0;
		int count=valuevector_vector.size();
		while(i<count)
		{
			result.append(valuevector_vector[i][j]);
			i++;
			if(i<count)
			{
				std::wstring comma;
				comma+=L',';
				result.append(comma);
			}
		}
		value_vector.push_back(result);
	}



}

void ProjectSerializer::parseTuple(std::wstring parvalue,std::vector<std::wstring> &tuplevector)
{
	int i=0;
	int length=parvalue.size();
	int begin;
	int end;
	std::wstring str;
	while(i<length)
	{
		if(parvalue[i]==L'(')
		{
			i++;
			begin=i;
		}
		if(parvalue[i]==L')')
		{
			end=i;
			str=parvalue.substr(begin,end-begin);
			tuplevector.push_back(str);
			i++;
		}
		else
		{
			i++;
		}
	}

}
void ProjectSerializer::parseVector(std::vector<std::wstring> tuplevector, std::vector<std::vector<std::wstring> > &valuevector_vector)
{
	std::vector<std::wstring>::iterator itr=tuplevector.begin();
	while(itr!=tuplevector.end())
	{
		parseSingleTuple(*itr,valuevector_vector);
		itr++;
	}
}

void ProjectSerializer::parseSingleTuple(std::wstring singletuple,std::vector<std::vector<std::wstring> > &valuevector_vector)
{
	int i=0;
	int begin=0;
	int end;
	int length=singletuple.size();
	std::wstring str;
	std::vector<std::wstring> temp_vector;
	while(i<length)
	{
		if(singletuple[i]==L',')
		{
			end=i;
			str=singletuple.substr(begin,end-begin);
			temp_vector.push_back(str);
			i++;
			begin=i;
		}
		else
		{
			i++;
		}
			
	}
	str=singletuple.substr(begin,length-begin);
	temp_vector.push_back(str);
	valuevector_vector.push_back(temp_vector);
}

} // end of namespace DESpot


				                
