/*
 *  
 *  $Id: parserxmlenglish.cpp $
 *  Ginkgo CADx Project
 *
 *  Copyright 2008-12 MetaEmotion S.L. All rights reserved.
 *  http://ginkgo-cadx.com
 *
 *  This file is licensed under LGPL v3 license.
 *  See License.txt for details
 *
 *
 */
//#define _GINKGO_TRACE

#include <string>
#include <map>
#include <ctime>
#include <sstream>

#include <wx/xml/xml.h>
#include <wx/file.h>
#include <wx/filename.h>
#include <wx/sstream.h>
#include <wx/msgdlg.h>
#ifndef _WIN32
#include <signal.h>
#endif
#include <wx/tokenzr.h>
#include <main/controllers/configurationcontroller.h>
#include <wx/filename.h>


#include "parserxmlenglish.h"
#include <api/globals.h>
#include <api/imodelohl7.h>
#include <api/controllers/imodulecontroller.h>
#include <api/integration/dict.h>
#include <api/helpers/aetwildcards.h>
#include <main/controllers/controladorextensiones.h>
#include <main/controllers/controladorlog.h>
#include <main/entorno.h>
#include "dcmtk/dicomservers.h"

//creacion de la base de datos de mensajes
GIL::ParserXMLEnglish::ParserXMLEnglish()
{
}

GIL::ParserXMLEnglish::~ParserXMLEnglish()
{
}

//region "Interfaz generica"

std::list<std::string> GIL::ParserXMLEnglish::GetKeys()
{
	std::list<std::string> list;
	list.push_back("gnkworkflows");
	list.push_back("gnkworkflow");
	return list;
}

/* Parsea la cadena XML y construye el modelo de integracion. Los parametros no encontrados se asignan por defecto segun lo especificado en la configuracion global */
void GIL::ParserXMLEnglish::ParseIntegrationXML(GIL::IntegrationModelList& models, wxXmlNode* pRoot) 
{
	MapaServers servers;
	std::string xpp; // XML Pretty Printed for extended information info.
	// PreCargamos la lista de PACS de la configuracion
	for (DicomServerHolder* sl = DicomServerList::Instance()->GetList(); sl != NULL; sl = sl->next) {
		IModeloPACSServer pacs;
		pacs.sid = sl->server.ID;
		pacs.AET = sl->server.AET;
		pacs.hostname = sl->server.HostName;
		pacs.puerto = sl->server.Port;

		servers[pacs.sid] = pacs;
	}
	//	

	if (pRoot->GetName().CmpNoCase(wxT("gnkworkflows")) == 0) {

		wxString propVal;

		// Parseamos los PACS especificados por fichero
		for (wxXmlNode* nodo = pRoot->GetChildren(); nodo != NULL; nodo = nodo->GetNext()) {
			if (nodo->GetName().CmpNoCase(wxT("pacs")) == 0) { // Configuracion de PACS
				GIL::IModeloPACSServer pacsServer;

				propVal = nodo->GetPropVal(wxT("sid"), wxEmptyString);
				if( !propVal.empty() ) {
					pacsServer.sid = propVal.ToUTF8();
				}
				else {
					throw IntegrationException(_Std("Omitted Identificator"), xpp, "CONF/pacs");
				}

				propVal = nodo->GetPropVal(wxT("aet"), wxEmptyString);
				if( !propVal.empty() ) {
					pacsServer.AET = propVal.ToUTF8();
				}
				else {
					throw IntegrationException(_Std("Omitted AET"), xpp, "CONF/pacs");
				}

				propVal = nodo->GetPropVal(wxT("hostname"), wxEmptyString);
				if( !propVal.empty() ) {
					pacsServer.hostname = propVal.ToUTF8();
				}
				else {
					throw IntegrationException(_Std("Hostname missing"), xpp, "CONF/pacs");
				}

				propVal = nodo->GetPropVal(wxT("port"), wxEmptyString);
				if( !propVal.empty() ) {
					pacsServer.puerto = propVal.ToUTF8();
				}
				else {
					throw IntegrationException(_Std("Omitted port"), xpp, "CONF/pacs");
				}
				
				propVal = nodo->GetPropVal(wxT("tls"), wxEmptyString);
				if( propVal.CmpNoCase(wxT("yes")) == 0 || propVal.CmpNoCase(wxT("true")) == 0 || propVal.CmpNoCase(wxT("si")) == 0 || propVal.CmpNoCase(wxT("1")) == 0 ) {
					pacsServer.tls = true;
				}
				else {
					pacsServer.tls = false;
				}

				propVal = nodo->GetPropVal(wxT("pacs-user"), wxEmptyString);
				if( !propVal.empty()) {
					pacsServer.user = propVal.ToUTF8();
				}

				propVal = nodo->GetPropVal(wxT("pacs-password"), wxEmptyString);
				if( !propVal.empty()) {
					pacsServer.password = propVal.ToUTF8();
				}

				propVal = nodo->GetPropVal(wxT("verify-credentials"), wxEmptyString);
				if( propVal.CmpNoCase(wxT("yes")) == 0 || propVal.CmpNoCase(wxT("true")) == 0 || propVal.CmpNoCase(wxT("si")) == 0 || propVal.CmpNoCase(wxT("1")) == 0 ) {
					pacsServer.verify = true;
				}
				else {
					pacsServer.verify = false;
				}

				propVal = nodo->GetPropVal(wxT("retrieve-method"), wxEmptyString);
				if( propVal.CmpNoCase(wxT("get")) == 0 ) {
					pacsServer.metodo = GIL::IModeloPACSServer::IMPS_GET;
				}
				else {
					pacsServer.metodo = GIL::IModeloPACSServer::IMPS_MOVE;
				}
				
				propVal = nodo->GetPropVal(wxT("pdu"), wxEmptyString);
				if( propVal.empty()) {
					pacsServer.pdu = "16384";
				}
				else {
					pacsServer.pdu = propVal.ToUTF8();
				}

				propVal = nodo->GetPropVal(wxT("retrieve-level"), wxEmptyString);
				if( propVal.empty()) {
					pacsServer.retrieveLevel = "SERIES";
				}
				else {
					pacsServer.retrieveLevel = propVal.ToUTF8();
				}

				propVal = nodo->GetPropVal(wxT("charset"), wxEmptyString);
				if( !propVal.empty() ) {
					pacsServer.defaultCharset = propVal.ToUTF8();
				}
				else {
					pacsServer.defaultCharset = "ISO_IR 100";
				}

				for (wxXmlNode* subnodo = nodo->GetChildren(); subnodo != NULL; subnodo = subnodo->GetNext()) {
					if (subnodo->GetName().CmpNoCase(wxT("client-cert")) == 0) {
						pacsServer.cert = subnodo->GetNodeContent().ToUTF8();
					}
					else if (subnodo->GetName().CmpNoCase(wxT("client-key")) == 0) {
						pacsServer.key = subnodo->GetNodeContent().ToUTF8();
					}
				}

				servers[pacsServer.sid] = pacsServer;
				try{
					DicomServer* server = DicomServerList::Instance()->GetServer(pacsServer.sid);
					server->AET = pacsServer.AET;
					server->HostName = pacsServer.hostname;
					long puerto;
					long pdu;
					if(!wxString::FromUTF8(pacsServer.pdu.c_str()).ToLong(&pdu)) {
						throw IntegrationException(_Std("The pdu size is not a valid number"), xpp, "CONF/pacs");
					}
					server->PDU = pdu;
					if(wxString::FromUTF8(pacsServer.puerto.c_str()).ToLong(&puerto)) {
						server->Port = puerto;
					} else {
						throw IntegrationException(_Std("Port is not a valid number"), xpp, "CONF/pacs");
					}
					if (pacsServer.metodo == GIL::IModeloPACSServer::IMPS_GET) {
						server->retrieveWithMove = false;
					}
					else {
						server->retrieveWithMove = true;
					}
					server->retrieveSeries = wxString::FromUTF8(pacsServer.retrieveLevel.c_str()).CmpNoCase(wxT("SERIES")) == 0;
					server->useTLS = pacsServer.tls;
					server->verifyCredentials = pacsServer.verify;
					server->certificate = pacsServer.cert;
					server->privateKey  = pacsServer.key;
					server->pacsUser = pacsServer.user;
					server->pacsPass = pacsServer.password;

					DicomServerList::Instance()->SetDefaultServer(server->ID);

				} catch (GinkgoNoServerFoundException& ){
					long puerto;
					long pdu;
					if(!wxString::FromUTF8(pacsServer.pdu.c_str()).ToLong(&pdu)) {
						throw IntegrationException(_Std("The pdu size is not a valid number"), xpp, "CONF/pacs");
					}
					if(wxString::FromUTF8(pacsServer.puerto.c_str()).ToLong(&puerto)) {
						DicomServerList::Instance()->AddServer( DicomServer(pacsServer.sid, pacsServer.AET, pacsServer.hostname, (int)puerto, 0, true, pdu, pacsServer.tls, pacsServer.user, pacsServer.password, pacsServer.metodo == GIL::IModeloPACSServer::IMPS_MOVE, wxString::FromUTF8(pacsServer.retrieveLevel.c_str()).Upper() == wxT("SERIES"), false, pacsServer.verify, pacsServer.cert, pacsServer.key, pacsServer.defaultCharset), true );
					} else {
						throw IntegrationException(_Std("The port is not a valid number"), xpp, "CONF/pacs");
					}
				}
			}
		}

		// Parseamos las gnkworkflows
		for (wxXmlNode* nodo = pRoot->GetChildren(); nodo != NULL; nodo = nodo->GetNext()) {
			if (nodo->GetName().CmpNoCase(wxT("gnkworkflow") ) == 0)  { // gnkworkflow
				GIL::IModeloIntegracion* modelo = ParseGnkWorkflow(nodo, servers);
				models.push_back(modelo);
			} //fin gnkworkflow
		} //fin de parseo de gnkworkflows
	} else if (pRoot->GetName().CmpNoCase(wxT("gnkworkflow")) == 0) {
		GIL::IModeloIntegracion* modelo = ParseGnkWorkflow(pRoot, servers);
		models.push_back(modelo);
	} else {
		throw IntegrationException(_Std("Setting not found"), xpp, "CONF");
	}
}

GIL::IModeloIntegracion* GIL::ParserXMLEnglish::ParseGnkWorkflow(wxXmlNode* nodo, GIL::ParserXMLEnglish::MapaServers& servers)
{	
	std::string xpp; // XML Pretty Printed for extended information info.
	wxString propVal;
	GIL::IModeloIntegracion* modelo = new IModeloIntegracion();
	//se copia el raw data
	{
		wxXmlNode* pNodo = new wxXmlNode(*nodo);
		wxXmlDocument docTmp;
		docTmp.SetRoot(pNodo);
		wxStringOutputStream out;
		docTmp.Save(out,wxXML_NO_INDENTATION);
		modelo->rawXmlData = out.GetString().ToUTF8();
	}
	//

	propVal = nodo->GetPropVal(wxT("tid"), wxEmptyString);
	if( !propVal.empty() ) {
		modelo->idPlantilla = propVal.ToUTF8();
	} else {
		modelo->idPlantilla = "";
	}

	propVal = nodo->GetPropVal(wxT("action"), wxEmptyString).Lower();
	if ( !propVal.empty() ) {

		if (propVal.CmpNoCase(wxT("retrieve")) == 0){
			modelo->accion = GIL::IModeloIntegracion::TA_Obtener;
		}
		else if (propVal.CmpNoCase(wxT("dicomize")) == 0 ) {
			modelo->accion = GIL::IModeloIntegracion::TA_Dicomizar;
		}
		else if (propVal.CmpNoCase(wxT("print")) == 0) {
			modelo->accion = GIL::IModeloIntegracion::TA_Imprimir;
		}
		else if (propVal.CmpNoCase(wxT("open")) == 0) {
			modelo->accion = GIL::IModeloIntegracion::TA_Open;
		}
		else {
			throw IntegrationException(_Std("\"action\" attribute invalid at \"gnkworkflow\" scope" ), xpp, "CONF/template");
		}
	}
	else {
		throw IntegrationException(_Std("\"action\" attribute expected at \"gnkworkflow\" scope"), xpp, "CONF/template");
	}

	propVal = nodo->GetPropVal(wxT("petition-id"), wxEmptyString);
	if( !propVal.empty() ) {
		modelo->GlobalVariables.InsertVariable(GKDI_HCE_PETITION_ID, std::string(propVal.ToUTF8()));
	}

	propVal = nodo->GetPropVal(wxT("scope"), wxEmptyString);
	if( !propVal.empty() ) {
		modelo->GlobalVariables.InsertVariable(GKDI_JIMENA_AMBITO_PETICION,std::string(propVal.ToUTF8()));
	}

	if( nodo->HasProp(wxT("pacs-retrieve-sid")) ) {
		propVal = nodo->GetPropVal(wxT("pacs-retrieve-sid"), wxEmptyString);
		if (!propVal.IsEmpty()) {
			modelo->GlobalVariables.InsertVariable(GKDI_GLOBAL_PACS_RETRIEVE_SID, std::string(propVal.ToUTF8()));
		}	
		else {
			throw IntegrationException(_Std("\"pacs-retrieve-sid\" attribute empty at \"gnkworkflow\" scope"), xpp, "CONF/template");
		}		
	}

	if( nodo->HasProp(wxT("pacs-store-sid")) ) {
		propVal = nodo->GetPropVal(wxT("pacs-store-sid"), wxEmptyString);
		if (!propVal.IsEmpty()) {
			modelo->GlobalVariables.InsertVariable(GKDI_GLOBAL_PACS_STORE_SID, std::string(propVal.ToUTF8()));
		}	
		else {
			throw IntegrationException(_Std("\"pacs-store-sid\" attribute empty at \"gnkworkflow\" scope"), xpp, "CONF/template");
		}		
	}

	//recorremos los hijos de las gnkworkflows
	for (wxXmlNode* hijo = nodo->GetChildren(); hijo != NULL; hijo = hijo->GetNext()) {
		//files...
		if (hijo->GetName().CmpNoCase(wxT("file")) == 0 && hijo->GetChildren() != NULL){
			modelo->Files.push_back(std::string(hijo->GetChildren()->GetContent().ToUTF8()));
		}
		//parseamos los campos dimse
		if(hijo->GetName().CmpNoCase(wxT("query-retrieve-level")) == 0){
			propVal = hijo->GetPropVal(wxT("value"), wxEmptyString);
			if ( !propVal.empty() ) {
				modelo->TagsDICOMOverwrite.tags["0008|0052"] = std::string(propVal.Upper().ToUTF8());
			}
			else {
				throw IntegrationException(_Std("\"value\" attribute expected at \"query-retrieve-level\" scope"), xpp, "CONF/template");
			}
		}

		//parseamos los campos d paciente
		if(hijo->GetName().CmpNoCase(wxT("patient")) == 0) {
			for (wxXmlNode* hijosPaciente = hijo->GetChildren(); hijosPaciente != NULL; hijosPaciente = hijosPaciente->GetNext()) {
				if(hijosPaciente->GetName().CmpNoCase(wxT("name")) == 0) {
					if(hijosPaciente->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_PATIENT_NAME, std::string(hijosPaciente->GetChildren()->GetContent().ToUTF8()));
					}
				} else if(hijosPaciente->GetName().CmpNoCase(wxT("first-surname")) == 0) {
					if(hijosPaciente->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_PATIENT_FAMILY_NAME, std::string(hijosPaciente->GetChildren()->GetContent().ToUTF8()));
					}
				} else if(hijosPaciente->GetName().CmpNoCase(wxT("second-surname")) == 0) {
					if(hijosPaciente->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_PATIENT_SECOND_FAMILY_NAME, std::string(hijosPaciente->GetChildren()->GetContent().ToUTF8()));
					}
				} else if(hijosPaciente->GetName().CmpNoCase(wxT("episode-number")) == 0) {
					if(hijosPaciente->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_HCE_EPISODE_NUMBER, std::string(hijosPaciente->GetChildren()->GetContent().ToUTF8()));
					}
				}else if(hijosPaciente->GetName().CmpNoCase(wxT("id")) == 0) {
					std::string codigo(propVal.ToUTF8());
					std::string valor(propVal.ToUTF8());
					propVal = hijosPaciente->GetPropVal(wxT("code"), wxEmptyString);
					if ( !propVal.empty() ) {
						codigo =  propVal.ToUTF8();
					}
					else {
						throw IntegrationException(_Std("\"code\" attribute expected at \"patient\" scope"), xpp, "CONF/template");
					}
					propVal = hijosPaciente->GetPropVal(wxT("value"), wxEmptyString);
					if ( !propVal.empty() ) {
						valor =  propVal.ToUTF8();
						if (!modelo->GlobalVariables.Contains(GKDI_PATIENT_ID)) {
							modelo->GlobalVariables.InsertVariable(GKDI_PATIENT_ID, valor);
						}
					}								
				}
			}
		}//fin paciente

		//parseamos los campos d medico
		if(hijo->GetName().CmpNoCase(wxT("physician")) == 0) {
			for (wxXmlNode* hijosMedico = hijo->GetChildren(); hijosMedico != NULL; hijosMedico = hijosMedico->GetNext()) {
				if(hijosMedico->GetName().CmpNoCase(wxT("name")) == 0) {
					if(hijosMedico->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_REFERRING_PHISICIAN_NAME, std::string(hijosMedico->GetChildren()->GetContent().ToUTF8()));
					}
				} else if(hijosMedico->GetName().CmpNoCase(wxT("first-surname")) == 0) {
					if(hijosMedico->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_REFERRING_PHISICIAN_FAMILY_NAME, std::string(hijosMedico->GetChildren()->GetContent().ToUTF8()));
					}
				} else if(hijosMedico->GetName().CmpNoCase(wxT("second-surname")) == 0) {
					if(hijosMedico->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_REFERRING_PHISICIAN_SECOND_FAMILY_NAME, std::string(hijosMedico->GetChildren()->GetContent().ToUTF8()));
					}
				} else if(hijosMedico->GetName().CmpNoCase(wxT("id")) == 0) {
					std::string codigo(propVal.ToUTF8());
					std::string valor(propVal.ToUTF8());
					propVal = hijosMedico->GetPropVal(wxT("code"), wxEmptyString);
					if ( !propVal.empty() ) {
						codigo =  propVal.ToUTF8();
					}
					else {
						throw IntegrationException(_Std("\"code\" attribute expected at \"physician\" scope"), xpp, "CONF/template");
					}
					propVal = hijosMedico->GetPropVal(wxT("value"), wxEmptyString);
					if ( !propVal.empty() ) {
						valor =  propVal.ToUTF8();
					}
					else {
						throw IntegrationException(_Std("\"value\" attribute expected at \"physician\" scope"), xpp, "CONF/template");
					}
					if (!modelo->GlobalVariables.Contains(GKDI_REFERRING_PHISICIAN_ID)) {
						modelo->GlobalVariables.InsertVariable(GKDI_REFERRING_PHISICIAN_ID, valor);
					}
				} else if(hijosMedico->GetName() == wxT("institution")) {
					propVal = hijosMedico->GetPropVal(wxT("iid"), wxEmptyString);
					if ( !propVal.empty() ) {
						modelo->GlobalVariables.InsertVariable(GKDI_REFERRING_PHISICIAN_INSTITUTION_ID, std::string(propVal.ToUTF8()));
					}
					else {
						throw IntegrationException(_Std("\"iid\" atribute expected at \"institution\" scope"), xpp, "CONF/template");
					}

					if(hijosMedico->GetChildren() != NULL){
						modelo->GlobalVariables.InsertVariable(GKDI_REFERRING_PHISICIAN_INSTITUTION_NAME, std::string(hijosMedico->GetChildren()->GetContent().ToUTF8()));
					}
				}
			}
		}//fin medico

		if(hijo->GetName().CmpNoCase(wxT("hce")) == 0) {
			propVal = hijo->GetPropVal(wxT("aid"), wxEmptyString);
			if ( !propVal.empty() ) {
				modelo->GlobalVariables.InsertVariable(GKDI_HCE_ID, std::string(propVal.ToUTF8()));
			}
			else {
				throw IntegrationException(_Std("\"aid\" attribute expected at \"hce\" scope"), xpp, "CONF/template");
			}
		}

		if (hijo->GetName().CmpNoCase(wxT("metadata")) == 0) {
			std::string codigo;
			std::string clave;
			std::string valor;
			std::string descripcion;

			propVal = hijo->GetPropVal(wxT("code"), wxEmptyString);
			if ( !propVal.empty() ) {
				codigo = propVal.Upper().ToUTF8();
			}else {
				throw IntegrationException(_Std("\"code\" attribute expected at \"metadata\" scope"), xpp, "CONF/template");
			}

			propVal = hijo->GetPropVal(wxT("key"), wxEmptyString);
			if ( !propVal.empty() ) {
				clave = propVal.Lower().ToUTF8();
			}else {
				throw IntegrationException(_Std("\"key\" attribute expected at \"metadata\" scope"), xpp, "CONF/template");
			}

			propVal = hijo->GetPropVal(wxT("value"), wxEmptyString);
			if ( !propVal.empty() ) {
				valor = propVal.ToUTF8();
			}

			propVal = hijo->GetPropVal(wxT("description"), wxEmptyString);
			if ( !propVal.empty() ) {
				descripcion = propVal.ToUTF8();
			}

			if (codigo == "DICOM") {
				modelo->TagsDICOMOverwrite.tags[clave] = valor;
			} else {
				modelo->GlobalVariables.InsertVariable(clave, valor, descripcion);
			}
		}

		if (hijo->GetName().CmpNoCase(wxT("observations")) == 0) {
			if(hijo->GetChildren() != NULL) {
				modelo->GlobalVariables.InsertVariable(GKDI_GLOBAL_OBSERVATIONS, std::string(hijo->GetChildren()->GetContent().ToUTF8()));
			}
		}

		if (hijo->GetName().CmpNoCase(wxT("message_template")) == 0) {
			if(hijo->GetChildren() != NULL) {
				modelo->messageTemplate = std::string(hijo->GetChildren()->GetContent().ToUTF8());
			}
		}
	}//fin hijos gnkworkflow

	//insert tags dicom...
	if (modelo->accion == GIL::IModeloIntegracion::TA_Dicomizar) {
		//only overwrite en dicomize no en obtain....
		if (modelo->GlobalVariables.Contains(GKDI_PATIENT_ID)) {
			modelo->TagsDICOMOverwrite.tags["0010|0020"] = modelo->GlobalVariables.GetValue(GKDI_PATIENT_ID);
		}
		if (modelo->GlobalVariables.Contains(GKDI_PATIENT_NAME)) {
			std::ostringstream ostr;
			ostr << modelo->GlobalVariables.GetValue(GKDI_PATIENT_FAMILY_NAME);
			if (modelo->GlobalVariables.Contains(GKDI_PATIENT_SECOND_FAMILY_NAME)) {
				ostr << " " << modelo->GlobalVariables.GetValue(GKDI_PATIENT_SECOND_FAMILY_NAME);
			}
			ostr << "^" << modelo->GlobalVariables.GetValue(GKDI_PATIENT_NAME);
			modelo->TagsDICOMOverwrite.tags["0010|0010"] = ostr.str();
		}
		if (modelo->GlobalVariables.Contains(GKDI_REFERRING_PHISICIAN_NAME)) {
			std::ostringstream ostr;
			ostr << modelo->GlobalVariables.GetValue(GKDI_REFERRING_PHISICIAN_FAMILY_NAME);
			if (modelo->GlobalVariables.Contains(GKDI_REFERRING_PHISICIAN_SECOND_FAMILY_NAME)) {
				ostr << " " << modelo->GlobalVariables.GetValue(GKDI_REFERRING_PHISICIAN_SECOND_FAMILY_NAME);
			}
			ostr << "^" << modelo->GlobalVariables.GetValue(GKDI_REFERRING_PHISICIAN_NAME);
			modelo->TagsDICOMOverwrite.tags["0008|0090"] = ostr.str();
		}
		if (modelo->GlobalVariables.Contains(GKDI_REFERRING_PHISICIAN_INSTITUTION_NAME)) {
			modelo->TagsDICOMOverwrite.tags["0008|0080"] = modelo->GlobalVariables.GetValue(GKDI_REFERRING_PHISICIAN_INSTITUTION_NAME);
		}
		if (!modelo->GlobalVariables.Contains(GKDI_HCE_PETITION_ID)) {
			throw IntegrationException(_Std("\"petition-id\" attribute expected at \"gnkworkflow\" scope"), xpp, "CONF/template");
		}
	} else if (modelo->accion == GIL::IModeloIntegracion::TA_Obtener) {
		if (modelo->TagsDICOMOverwrite.tags.empty()) {
			throw IntegrationException(_Std("You must specify attributes you want to use in the query"), xpp, "CONF/template");
		}
	}
	if(!modelo->GlobalVariables.Contains(GKDI_HCE_ID)) {
		throw IntegrationException(_Std("id_application expected"), xpp, "CONF/template");
	}
	if (!modelo->GlobalVariables.Contains(GKDI_PATIENT_ID) && modelo->accion == GIL::IModeloIntegracion::TA_Dicomizar) {
		throw IntegrationException(_Std("It has been read a \"patient\" tag without identifiers"), xpp, "CONF/template");
	}
	//se pone el codigo de aplicacion y el primer PACS de la configuracion si no nos ha venido  ninguno
	std::string codigoAplicacion;
	GNC::GCS::ConfigurationController::Instance()->readStringGeneral("/GinkgoCore/HCE","CodigoAplicacion", codigoAplicacion);
	modelo->GlobalVariables.InsertVariable(GKDI_GLOBAL_APPLICATION_CODE, codigoAplicacion);
	if(!servers.empty()) {
		DicomServer* pServer = DicomServerList::Instance()->GetDefaultServer();
		if (!modelo->GlobalVariables.Contains(GKDI_GLOBAL_PACS_STORE_SID) && pServer != NULL) {
			modelo->GlobalVariables.InsertVariable(GKDI_GLOBAL_PACS_STORE_SID, pServer->ID);
		}
		if (!modelo->GlobalVariables.Contains(GKDI_GLOBAL_PACS_RETRIEVE_SID) && pServer != NULL) {
			modelo->GlobalVariables.InsertVariable(GKDI_GLOBAL_PACS_RETRIEVE_SID, pServer->ID);
		}
	}
	if ( (modelo->accion == GIL::IModeloIntegracion::TA_Dicomizar && !modelo->GlobalVariables.Contains(GKDI_GLOBAL_PACS_STORE_SID)) || 
		(modelo->accion == GIL::IModeloIntegracion::TA_Obtener && !modelo->GlobalVariables.Contains(GKDI_GLOBAL_PACS_RETRIEVE_SID)) ) 
	{
		throw IntegrationException(_Std("You must define a default PACS in the integration XML or in the settings menu"), xpp, "CONF/template");
	}
	return modelo;
}
