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

#include "ProjIntegrityAlgo.h"
#include "DesIntegrityAlgo.h"
#include "ProjectEvent.h"

namespace DESpot
{

const std::wstring ProjIntegrityAlgo::cProjIntegAlgoDesc = L"Project Integrity Algorithm:";

const std::wstring ProjIntegrityAlgo::cInvalidProjNameWarn = L"Invalid project name: %ls";

const std::wstring ProjIntegrityAlgo::cInvalidProjectEventErr = L"Invalid project event: %ls - %ls";

//_________________________________________________________________________________________________

ProjIntegrityAlgo::ProjIntegrityAlgo(bool runIncremental /*= true*/)
{
	m_runIncremental = runIncremental;
	m_description = cProjIntegAlgoDesc;
}

//_________________________________________________________________________________________________

ProjIntegrityAlgo::ProjIntegrityAlgo(DesProject* project, bool runIncremental /*= true*/)
{
	m_runIncremental = runIncremental;
	m_description = cProjIntegAlgoDesc;
	
	setInputProject(project);
}

//_________________________________________________________________________________________________

ProjIntegrityAlgo::~ProjIntegrityAlgo(void)
{
}

//_________________________________________________________________________________________________

void ProjIntegrityAlgo::setInputProject(DesProject* project)
{
	m_project = project;
	addError(cNotCheckedErr);
}

//_________________________________________________________________________________________________

//Overridable called from the "run" method of the base implementation of the algorithm
bool ProjIntegrityAlgo::verifyIntegrity()
{
	if (m_runIncremental && m_project->getIntegrity() == eIntegYes)
		return true;

	verifyProjectName();
	
	verifyProjectEvents();

	verifyDes();

	return isValid();
}

//_________________________________________________________________________________________________

//verifies the name of the project doesn't contain invalid characters
bool ProjIntegrityAlgo::verifyProjectName()
{
	NameValidator nameValidator(new AlphaNumValidator(new WordSepValidator()));
	if (nameValidator.validate(m_project->getName()) == false)
	{
		addWarning(errorMessage(cInvalidProjNameWarn, m_project->getName()));
		
		return false;
	}

	return true;
}

//_________________________________________________________________________________________________

//verifies that project events are consistently defined in the constituent DES
bool ProjIntegrityAlgo::verifyProjectEvents()
{
	bool verifOk = true;

	DesProject::EventIteratorPtr projEventIt = m_project->createProjEventIterator();
	for(projEventIt->first(); projEventIt->notDone(); projEventIt->next())
	{
		const ProjectEvent& projEvent = projEventIt->currentItem();

		//verify that the project event is valid
		std::wstring reason;
		if (projEvent.isValid(&reason) == false)
		{			
			addError(errorMessage(cInvalidProjectEventErr, projEvent.getName(), reason));
			verifOk = false;
		}
	}

	return verifOk;
}

//_________________________________________________________________________________________________

//verifies that all DES are valid
bool ProjIntegrityAlgo::verifyDes()
{
	bool verifOk = true;
	
	//verify the integrity of every DES in the project
	DesIntegrityAlgo desIntegAlgo;	
	DesProject::DesIteratorPtr desIt = m_project->createDesIterator();
	DesProject::DesIteratorPtr desIt2 = m_project->createDesIterator(eTemplateDes);
	for(desIt->first(); desIt->notDone(); desIt->next())
	{
		Des& des = desIt->currentItem();
		
		if (des.getIntegrity() != eIntegYes || !m_runIncremental)
		{
			if (des.checkIntegrity(desIntegAlgo) == false)
			{
				addError(desIntegAlgo.getErrorList());
				verifOk = false;
			}
		}
	}
	for(desIt2->first(); desIt2->notDone(); desIt2->next())
	{
		Des& des2 = desIt2->currentItem();
		
		if (des2.getIntegrity() != eIntegYes || !m_runIncremental)
		{
			if (des2.checkIntegrity(desIntegAlgo) == false)
			{
				addError(desIntegAlgo.getErrorList());
				verifOk = false;
			}
		}
	}
	return verifOk;
}

} //end of namespace DESpot
