wfStartLogicCall
Empty start logic

			true;
		

checkDataAndEndValidator
Questa validazione controlla che se il bando di finanziamento viene marcato come "con scadenza" allora deve essere specificata la data di scadenza
Per maggiori dettagli cfr. excel modello dati dell'entità Bando di finanziamento

		
			if(object.getBooleanMap().get("openEnded")!=null){
				if((object.getBooleanMap().get("openEnded")==false)&&(object.getDateMap().get("endDate")==null)){
					errors.reject("error.date.startDateEndDateNotCompatible");	
				}
			}			
		

isNotLegacyAndYearIsGreaterOrEqualThan2019Contract
Questa è la descrizione della logica di validazione Questa è un'applicability rule che viene valutata prima di eseguire altre validazioni.
Se ritorna true allora vengono eseguite le altre validazioni altrimenti no.
Oltre al check previsto da isNotLegacy , verifica anche che il contratto in questione sia relativo ad un anno maggiore o uguale a 2019, altrimenti vengono disattivate le validazioni e le sincronizzazioni.
Questo approccio è stao scelto per evitare lo scatenarsi delle validazioni su vecchi contratti che non rispettano le nuove e più stringenti validazioni, ed evitare quindi di dovere fare una bonifica a tappeto.

	
			(
				object.getYear()!=null 
				&& 
				object.getYear().compareTo(2019)>=0
			) 
			&& 
			(
				object.getBooleanMap().get('legacy')==null 
				|| 
				Packages.java.lang.Boolean.FALSE.equals(object.getBooleanMap().get('legacy'))
			)
		

wfIdentityLogicResearchDivisionProjectPermissionsJs
Questa è una permissions logic che costruisce dinamicamente i permessi per i contratti per il team Divisione Ricerca.
Se l'utente che sta effettuando la creazione del contratto appartiene alla Divisione Ricerca, vengono assegnati i permessi di scrittura a questo team e quelli di sola lettura a livello dipartimentale.

			var wfTask=object;
			var wfItem=wfService.getWfItem(wfTask.getWfItemId());
			var permissions="r";			
			var hasPowerPermissions=Packages.it.cilea.wf.util.WfUtil.isAnyItemCreatorIdentityMatchingThisTaskIdentity(wfTask, wfService);			
			if (Packages.java.lang.Boolean.TRUE.equals(hasPowerPermissions))
				hasPowerPermissions=true;
			else 
				hasPowerPermissions=false;
			
			var hasHelpdeskStartedFlow=Packages.it.cilea.wf.util.WfUtil.isAnyItemCreatorIdentityMatchingAuthoritiesWithThisResource(wfTask, "/HELPDESK/ap/contract.profile", wfService, gaAuthorizationService);
			if (Packages.java.lang.Boolean.TRUE.equals(hasHelpdeskStartedFlow))
				hasHelpdeskStartedFlow=true;
			else 
				hasHelpdeskStartedFlow=false;				
						
			switch(String(wfItem.getWfState().getDescription())){
				case "draft": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow) 
						permissions="crwfd" 
					else 
						permissions="r";
				break;
				
				case "inquiry": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow) 
						permissions="rwfd" 
					else 
						permissions="r";
				break;
				
				case "fiscalCheck": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow)
						permissions="r" 
					else 
						permissions="r";
				break;
				
				case "revisionAfterFiscalCheck": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow) 
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "approval": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow) 
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "approvedAwaitingCountersignedContract": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow)
						permissions="rwf" 
					else 
						permissions="r";
				break;				
				
				case "signed": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow)
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "closed": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow)
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "suspended": 
					if(hasPowerPermissions||hasHelpdeskStartedFlow)
						permissions="rwf" 
					else 
						permissions="r";
				break;
			}
			
			wfTask.setPermissions(permissions);
			
		

wfIdentityLogicMultipleHeadOfDepartmentProjectPermissionsJs
Questa è una permissions logic che costruisce dinamicamente i permessi per i contratti per il team dipartimentali
Se l'utente che sta effettuando la creazione del contratto è in visione dipartimentale e appartiene ad un team dipartimentale, vengono assegnati i permessi di scrittura a questo team e quelli di sola lettura a livello Divisione Ricerca.

			var wfTask=object;
			var wfItem=wfService.getWfItem(wfTask.getWfItemId());
			var permissions="r";			
			var isOnlyRead=true;
			
			//recupero l'unità organizzativa associata (dipartimento) all'identity/team di questo task
			var organizationUnitFromIdentity=Packages.it.cilea.ga.util.GaUtil.getOrganizationUnitFromIdentyForDepartment(gaAuthorizationService.getIdentity(wfTask.getIdentityId()), gaService);			
			
			//recupero dall'item la lista dei dipartimenti
			var internalOrganizationUnitList=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem,
				"it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
			var internalOrganizationUnitListIterator = internalOrganizationUnitList.iterator();
			
			//controllo il ruolo del dipartimento
			//isOnlyRead è false se il dipartimento è principale
			//isOnlyRead è true se il dipartimento è aggregato
			while(internalOrganizationUnitListIterator.hasNext()){
				var internalOrganizationUnit=internalOrganizationUnitListIterator.next();
				var ou = internalOrganizationUnit.getOrganizationUnitMap().get("ouId");
				
				if (ou.getId().equals(organizationUnitFromIdentity.getId())){
					//cerco prima roleId che è il ruolo standard.
					//se non lo trovo ricado in ouRole che è quello legacy
					var role=internalOrganizationUnit.getWfDictionaryMap().get("roleId");
					if (role==null)
						role=internalOrganizationUnit.getWfDictionaryMap().get("ouRole");
					isOnlyRead=Packages.it.cilea.wf.util.WfUtil.isOnlyReadPermission(role, wfItem, "wfIdentityLogicMultipleHeadOfDepartment");
					if (Packages.java.lang.Boolean.TRUE.equals(isOnlyRead))
						isOnlyRead=true;
					else
						isOnlyRead=false;

					break;
				}					
			}
			
			//verifico se c'è match tra le identity di chi ha creato l'item e l'identity di questo task
			//serve per capire se il contratto in questione è stato creato da Divisione Ricerca o da Dipartimento
			//e per dare "power permissions" solo al team che ha fatto la creazione.
			var hasPowerPermissions=Packages.it.cilea.wf.util.WfUtil.isAnyItemCreatorIdentityMatchingThisTaskIdentity(wfTask, wfService);
			
			if (Packages.java.lang.Boolean.TRUE.equals(hasPowerPermissions))
				hasPowerPermissions=true;
			else {
				//se hasPowerPermissions è false allora dovrebbe essere stato creato dalla Divisione Ricerca
				//se però viene cambiato in corso d'opera il dipartimento, non ci sarà più match tra il team dipartimentale che ha creato l'item e il team dipartimentale che dovrebbe accederci.
				//per gestire questo scenario controllo se le identity di chi ha effettuao la creazione sono quelle dipartimentali.				
				var isItemCreatedByDepartmentAuthority=Packages.it.cilea.wf.util.WfUtil.isAllItemCreatorIdentityOfGivenAuthority(wfTask, wfService, gaAuthorizationService, "ROLE_DEPARTMENT");
				
				//se chi ha creato aveva identity dipartimentali...
				if (Packages.java.lang.Boolean.TRUE.equals(isItemCreatedByDepartmentAuthority)){															
					if (isOnlyRead)
						hasPowerPermissions=false;
					else 
						hasPowerPermissions=true;
				} else {
					//se chi ha creato NON aveva identity dipartimentali (Helpdesk o Divisione Ricerca)...
					hasPowerPermissions=false;
				}				
			}
			
			switch(String(wfItem.getWfState().getDescription())){
				case "draft": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="crwfd" 
					else 
						permissions="r";
				break;
				
				case "inquiry": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="rwfd" 
					else 
						permissions="r";
				break;
				
				case "fiscalCheck": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="r" 
					else 
						permissions="r";
				break;
				
				case "revisionAfterFiscalCheck": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "approval": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "approvedAwaitingCountersignedContract": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="rwf" 
					else 
						permissions="r";
				break;				
				
				case "signed": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "closed": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="rwf" 
					else 
						permissions="r";
				break;
				
				case "suspended": 
					if(hasPowerPermissions && !isOnlyRead) 
						permissions="rwf" 
					else 
						permissions="r";
				break;	
			}
			
			wfTask.setPermissions(permissions);			
					
		

wfStartLogicContract
Questa logica viene eseguita in fase di creazione di un nuovo contratto.
Vengono effettuate le seguenti operazioni:

Per maggiori dettagli cfr. excel modello dati dell'entità Progetto
			var person=wfItem.getPersonMap().get("owner");
			person=gaService.getPerson(person.getId());
			var startDate=wfItem.getDateMap().get("proposalStartDate");
			var ownerElement=new Packages.it.cilea.wf.model.WfItemElement();
			ownerElement.setDiscriminator("owner");
			ownerElement.setWfItemId(wfItem.getId());
			ownerElement.getPersonMap().put("ownerId", person);
			
			var ownerStartDateDefault = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.contract.ownerStartDate.default");
			if(ownerStartDateDefault != null && "true".equals(ownerStartDateDefault)){
				ownerElement.getDateMap().put("startDate", startDate);
			}
	
			wfService.saveOrUpdate(ownerElement);
			wfItem.getWfItemElementSet().add(ownerElement);
			wfItem.getPersonMap().put("owner", null);
			
			var positionLastSet = person.getPositionLastSet();											
			var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionLastSet, "research", "department");
			positionLastSetIterator=positionLastSet.iterator();											
			while (positionLastSetIterator.hasNext()){
				var position=positionLastSetIterator.next();
				if (maxPriority == null || maxPriority.equals(position.getPriority())) {
					if ("research".equals(position.getDiscriminator()) && "department"
								.equals(position.getOrganizationUnit().getOrganizationUnitType().getDescription())) {
						var internalOrganizationUnitElement=new Packages.it.cilea.wf.model.WfItemElement();
						internalOrganizationUnitElement.setDiscriminator("internalOrganizationUnit");
						internalOrganizationUnitElement.setWfItemId(wfItem.getId());
						var internalOrganizationUnitRoleId = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.contract.internalOrganizationUnit.role.main");
						var internalOrganizationUnitRole = wfService.getWfDictionary(new Packages.java.lang.Integer(internalOrganizationUnitRoleId));
						internalOrganizationUnitElement.getOrganizationUnitMap().put("ouId", position.getOrganizationUnit());
						internalOrganizationUnitElement.getWfDictionaryMap().put("ouRole", internalOrganizationUnitRole);
						wfService.saveOrUpdate(internalOrganizationUnitElement);
						wfItem.getWfItemElementSet().add(internalOrganizationUnitElement);
						break;
					}
				}
			}		
			
			var year=startDate.get(Packages.java.util.Calendar.YEAR);
			wfItem.setYear(new Packages.java.lang.Integer(year));
			
			true;
			
			

ownerValidatorContract
Questa validazione controlla che esista almeno un responsabile scientifico nel tab "Soggetti interni".
Dal punto di vista del modello dati si tratta degli elementi di tipo owner
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

			if (object.getId()==null){
				if (object.getPersonMap().get("owner")==null)
					errors.rejectValue("personMap[owner]","error.contract.owner.required");
			} else {
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				if (
				!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))
				&&
				ownerSet.size()<1 
				&& 
				object.getPersonMap().get("owner")==null
				)
					errors.reject("error.contract.owner.atLeast1");
			}
		

ownerValidatorWithStartEndDateContract

		
			if (object.getId()==null){
				if (object.getPersonMap().get("owner")==null)
					errors.rejectValue("personMap[owner]","error.contract.owner.required");
			} else {
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){
					if (ownerSet.size()<1 && object.getPersonMap().get("owner")==null)
						errors.reject("error.contract.owner.atLeast1");
						
					var ownerSetIterator=ownerSet.iterator();
					
					var wfItemStartDate=object.getDateMap().get("startDate");
					var wfItemEndDate=object.getDateMap().get("endDate");
					var formatter =  Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");
					var ownerWithWrongInterval=[];
								
					while (ownerSetIterator.hasNext()){										
						var owner=ownerSetIterator.next();
						var wfItemElementStartDate=owner.getDateMap().get("startDate");
						
						if( wfItemElementStartDate!= null && wfItemStartDate && (wfItemElementStartDate.before(wfItemStartDate) || (wfItemEndDate!=null && wfItemElementStartDate.after(wfItemEndDate)))  ){
							ownerWithWrongInterval.push(owner.getPersonMap().get("ownerId").getDisplayValue());
						}								
					}
					
					if (ownerWithWrongInterval.length>0){
						errors.reject("error.contract.owner.wrongInterval", [ownerWithWrongInterval.toString()], "error.contract.owner.wrongInterval");
					}
				}
			}	
		

contributorValidatorWithStartEndDateContract

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){						
				var contributorSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "contributor", wfService);
				if (contributorSet.size()>0){
					var contributorSetIterator=contributorSet.iterator();				
					var wfItemStartDate=object.getDateMap().get("startDate");
					var wfItemEndDate=object.getDateMap().get("endDate");
					var formatter =  Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");
					var contributorWithWrongInterval=[];
								
					while (contributorSetIterator.hasNext()){										
						var contributor=contributorSetIterator.next();												
						var wfItemElementStartDate=contributor.getDateMap().get("startDate");
						
						if( wfItemElementStartDate!= null && wfItemStartDate && (wfItemElementStartDate.before(wfItemStartDate) || (wfItemEndDate!=null && wfItemElementStartDate.after(wfItemEndDate)))  ){
							contributorWithWrongInterval.push(contributor.getPersonMap().get("contributorId").getDisplayValue());
						}								
					}
					
					if (contributorWithWrongInterval.length>0){
						errors.reject("error.contract.contributor.wrongInterval", [contributorWithWrongInterval.toString()], "error.contract.contributor.wrongInterval");
					}			
				}				
			}
		

administrativeOwnerValidatorContract
Questa validazione controlla che esista almeno un referente amministrativo nel tab "Soggetti interni".
Dal punto di vista del modello dati si tratta degli elementi di tipo administrativeOwner
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){						
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "administrativeOwner", wfService);
				if (ownerSet.size()<1)
					errors.reject("error.contract.administrativeOwner.atLeast1");
			}
		

organizationUnitValidatorContract
Questa validazione controlla che esista almeno una unità organizzativa interna nel tab "Soggetti interni".
Dal punto di vista del modello dati si tratta degli elementi di tipo internalOrganizationUnit
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

		
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
				if (orgUnitSet.size()<1)
					errors.reject("error.contract.multipleInternalOrganization.atLeast1");
			}		
		

organizationUnitRoleValidatorContract
Questa validazione controlla che esista almeno un dipartimento specificato e che uno ed uno solo sia marcato come "Principale"
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){			
				var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
				if (orgUnitSet.size()<1){
					errors.reject("error.contract.multipleInternalOrganization.atLeast1");
				} else {
					var internalOrganizationUnitCoordinatorRole=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.contract.internalOrganizationUnit.role.main");
					if (!internalOrganizationUnitCoordinatorRole){
						throw "Configuration variable ap.contract.internalOrganizationUnit.role.main MUST BE DEFINED"; 								
					} else {
						internalOrganizationUnitCoordinatorRole=new Packages.java.lang.Integer(internalOrganizationUnitCoordinatorRole);
					}
					var orgUnitSetIterator=orgUnitSet.iterator();
					var count=0;											
					while (orgUnitSetIterator.hasNext()){											
						var element=orgUnitSetIterator.next();												
						var ouRole=element.getWfDictionaryMap().get("ouRole");
						if (ouRole!=null && internalOrganizationUnitCoordinatorRole.equals(ouRole.getId())){
							count++;	
						}												
					}
					if (count==0){
						errors.reject("error.contract.multipleInternalOrganization.missingMain");
					}
					else if (count>1) {
						errors.reject("error.contract.multipleInternalOrganization.tooManyMain");
					}
				}     
			}   								       										
		

ownerAndOrganizationUnitMatchValidatorContract
Questa validazione controlla che esista per ogni responsabile scientifico del contratto, una unità organizzativa che sia interna nel momento della data di avvio del progetto (startDate) oppure se non c'è questa data, in questo momento.
dal punto di vista del modello sono dei dati di tipo: internalOrganizationUnit, owner
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				var ownerDepartmentSet=new Packages.java.util.HashSet();
				var internalOrganizationUnitSet=new Packages.java.util.HashSet();
				
				var startDateFromWfItem=wfItem.getDateMap().get("startDate");
				if (startDateFromWfItem!=null){	
					startDateFromWfItem=startDateFromWfItem.getTime();	
				
					if (ownerSet.size()>0){
						var ownerSetIterator=ownerSet.iterator();			
						while (ownerSetIterator.hasNext()){
							var ownerElement=ownerSetIterator.next();			
							var person=ownerElement.getPersonMap().get("ownerId");
							
							var ownerDepartmentPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
							ownerDepartmentPositionSearch.setPersonId(person.getId());
							ownerDepartmentPositionSearch.setDate(startDateFromWfItem);
							ownerDepartmentPositionSearch.setOrganizationUnitTypeDescription("department");
							ownerDepartmentPositionSearch.setDiscriminator("research");							
							var ownerDepartmentPositionSet = gaService.getPositionSearchList(ownerDepartmentPositionSearch, 0);
							var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(ownerDepartmentPositionSet, "research", "department");
							
							var ownerDepartmentPositionSetIterator=ownerDepartmentPositionSet.iterator();							
							while (ownerDepartmentPositionSetIterator.hasNext()){
								var position=ownerDepartmentPositionSetIterator.next();
								if (maxPriority == null || maxPriority.equals(position.getPriority())) {
									ownerDepartmentSet.add(position.getOrganizationUnit());														
									break;
								}
							}
						}
					}
					if (ownerDepartmentSet.size()>0){
						if (orgUnitSet.size()>0){
				 			var orgUnitSetIterator=orgUnitSet.iterator();			
							while (orgUnitSetIterator.hasNext()){											
								var wfItemElement=orgUnitSetIterator.next();												
								var orgUnit=wfItemElement.getOrganizationUnitMap().get("ouId");
								internalOrganizationUnitSet.add(orgUnit);
							}
						}
					}
					
					if(!internalOrganizationUnitSet.containsAll(ownerDepartmentSet)){
						var nonMatchedDepartmentCollection=Packages.org.apache.commons.collections.CollectionUtils.subtract(ownerDepartmentSet, internalOrganizationUnitSet);
						var nonMatchedDepartmentCollectionIterator=nonMatchedDepartmentCollection.iterator();
						var nonMatchedDepartmentString="";
						var counter=0;
						while(nonMatchedDepartmentCollectionIterator.hasNext()){
							var nonMatchedDepartment=nonMatchedDepartmentCollectionIterator.next();
							if (counter++>0)
								nonMatchedDepartmentString+=", ";
							nonMatchedDepartmentString+=nonMatchedDepartment.getDescription();
						}
						var df =  Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");
						var dateAsString=df.format(startDateFromWfItem);
						errors.reject("error.contract.multipleInternalOrganization.matchWithDepartmentOwnerNotFound", [dateAsString, nonMatchedDepartmentString], null);       								
					}        
				}	
			}							       										
		

customerValidatorContract
Questa validazione controlla che esista almeno un committente nel tab "Dati generali".
Dal punto di vista del modello dati si tratta degli elementi di tipo customer
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

		
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){					
				var customerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "customer", wfService);
				if (customerSet.size()<1)
					errors.reject("error.contract.customer.atLeast1");        						
			}		       										
		

currencyAndTotalAmountValidatorContract
Questa validazione controlla che nel tab "Corrispettivi", nel caso di selezione di valuta diversa da EURO, vengano specificati


Dal punto di vista del modello dati si tratta degli attributi: Per maggiori dettagli cfr. excel modello dati dell'entità Contratto
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				var currency = object.getWfDictionaryMap().get("currency");	
				if(currency != null){
					var currencyId = object.getWfDictionaryMap().get("currency").getId();
					var dictionary = wfService.getWfDictionary(currencyId);
					var currencyCode = dictionary.getStringMap().get("code");
				
					if (currencyCode != "currency.eur"){
						if (!object.getNumberMap().get("totalAmountOriginalCurrency")){       										
							errors.rejectValue("numberMap[totalAmountOriginalCurrency]","error.contract.funding.totalAmountOriginalCurrency.required");									
						}
						if (!object.getNumberMap().get("exchangeRate")){
							errors.rejectValue("numberMap[exchangeRate]","error.contract.funding.exchangeRate.required");									
						}
						if (!object.getDateMap().get("exchangeRateDate")){
							errors.rejectValue("dateMap[exchangeRateDate]","error.contract.funding.exchangeRateDate.required");									
						}
					}
				}				
				
			}	       							        								       										
		

wfUgovPjSenderValidatorContract
Questa logica, effettua check di consistenza sulle mappature degli oggetti IRIS/UGOV e, se superati, invia il contratto verso UGOV PJ rispettando le regole di NON SOVRASCRITTURA lato UGOV PJ.
Per maggiori dettagli su queste regole consultare il team di UGOV PJ.
Le controparti dei contratti IRIS vengono create su UGOV con le regole di mappature delle tassonomie che vengono condivise in fase di attivazione.
Se in corso d'opera dovesse nascere l'esigenza di censire delle nuove tipologie è possibile contattare l'HD.
Di seguito vengono riportate le informazioni inviate ad UGOV PJ, con la specifica dell'attributo del modello dell'entità Contratto IRIS


Per maggiori dettagli cfr. excel modello dati dell'entità Contratto
			var Logic = function(wfItem, dtoPj, superLogic, errors, messageUtil, request, gaService, wfService, wfTaskService, searchBuilderTemplate, log) {
			this.wfItem=wfItem;
			this.dtoPj=dtoPj;
			this.superLogic=superLogic;
			this.errors=errors;
			this.messageUtil=messageUtil;
			this.request=request;
			this.gaService=gaService;
			this.wfService=wfService;
			this.wfTaskService=wfTaskService;
			this.searchBuilderTemplate=searchBuilderTemplate;
			this.log=log;
			this.setInternalOrgUnitList = function() {
				var internalOrganizationUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);
				var internalOrganizationUnitSetIterator=internalOrganizationUnitSet.iterator();
				while (internalOrganizationUnitSetIterator.hasNext()){
					var element=internalOrganizationUnitSetIterator.next();
					var orgUnit = element.getOrganizationUnitMap().get("ouId");
					var orgUnitRole = element.getWfDictionaryMap().get("ouRole");
					dtoPj.getDTOUoPjs().add(superLogic.getOrganizationUnit(orgUnit, orgUnitRole, errors));
				}
			};			
			this.setFinanciers = function() {
				var sendCustomer2Ugov=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.contract.customer.send2ugov.enable");
				if (sendCustomer2Ugov && sendCustomer2Ugov.trim().equalsIgnoreCase("true")){
					var contractorSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement", "customer",wfService);
					var contractorSetIterator=contractorSet.iterator();
					while (contractorSetIterator.hasNext()){
						var element=contractorSetIterator.next();
						var organizationUnit = element.getOrganizationUnitMap().get("customerId");
						var enteFinanziatore = superLogic.getEnteFinanziatore(organizationUnit, this.getFinancing(), contractorSet.size(), errors);
						dtoPj.getDTOEfPjs().add(enteFinanziatore);
					}
				}
			};
			this.setPartners = function() {};
			this.getFinancing = function() {				
				return wfItem.getNumberMap().get("totalAmount");
			};
			this.getStartDate = function() {
				return wfItem.getDateMap().get("startDate");			    	
			};
			this.getEndDate = function() {
				return wfItem.getDateMap().get("endDate");			    
			};
			this.getIdentifier = function() {	
				return wfItem.getIdentifier();
			};
			this.getDescription = function() {
				if(wfItem.getDescription()!=null){
					var length=wfItem.getDescription().length();
					return wfItem.getDescription().substring(0,(length>255)?255:length);
				} else {
					return null;
				}
			};
			this.getCup = function() {
				var sendCup2Ugov = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.con.cup.send2ugov.enable");
				if (sendCup2Ugov && sendCup2Ugov.trim().equalsIgnoreCase("true")){
					return wfItem.getStringMap().get("cup");
				} else {
					return null;
				}		
			};
			this.getAcronym = function() {
				return wfItem.getStringMap().get("acronym");
			};
			this.getExternalDmsIdentifier = function() {
				return wfItem.getStringMap().get("externalDmsIdentifier");
			};						
			this.isSynchronizable = function() {
				var financing=this.getFinancing();
				var legacy=wfItem.getBooleanMap().get("legacy");
				if (Packages.java.lang.Boolean.TRUE.equals(legacy) || financing==null || Packages.java.math.BigDecimal.ZERO.equals(financing))
					return Packages.java.lang.Boolean.FALSE;
				else			    
					return Packages.java.lang.Boolean.TRUE;
			};
			this.getProjectType = function() {
				return superLogic.getProjectType(wfItem);
			};
			this.getFinanceSchema = function() {
				return this.getProjectType();
			};
			this.getPjInternalCode = function() {
				return null;
			};
			this.isContributorStartDateRequired = function() {						
				var contributorStartDateRequired=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.contract.contributor.starDate.required");
				if (contributorStartDateRequired){
					if (contributorStartDateRequired.trim().equalsIgnoreCase("true")){
						return Packages.java.lang.Boolean.TRUE;
					} else if (contributorStartDateRequired.trim().equalsIgnoreCase("false")){
						return Packages.java.lang.Boolean.FALSE;
					} else {
						throw "ap.contract.contributor.starDate.required MUST BE true or false";
					}
				} else {
					return Packages.java.lang.Boolean.TRUE;
				}							    
			};				
			this.isOwnerStartDateRequired = function() {
				var ownerStartDateRequired=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.contract.owner.starDate.required");
				if (ownerStartDateRequired){
					if (ownerStartDateRequired.trim().equalsIgnoreCase("true")){
						return Packages.java.lang.Boolean.TRUE;
					} else if (ownerStartDateRequired.trim().equalsIgnoreCase("false")){
						return Packages.java.lang.Boolean.FALSE;
					} else {
						throw "ap.contract.owner.starDate.required MUST BE true or false";
					}
				} else {
					return Packages.java.lang.Boolean.TRUE;
				}
			};
		};
		new Logic(wfItem, dtoPj, superLogic, errors, messageUtil, request, gaService, wfService, wfTaskService, searchBuilderTemplate, log);
		

uniqueIdentifierContract
Questa validazione controlla l'unicità dell'identificativo dell'oggetto.
Questa verifica viene fatta per i casi di generazione di codice "parlante" con possibile collisione con identificativi già presenti.

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var paramMap = new Packages.java.util.HashMap();
				paramMap.put("identifier", object.getIdentifier());			
				
				var count=searchBuilderTemplate.getSingleObject("getWfItemCount", paramMap);
				if (count>1)
					errors.reject("error.contract.identifier.notUnique");			
			}
		

fiscalCheckFieldsetValidatorContract
Questa validazione impedisce l'edit degli attributi

relativi alla sezione "Controllo fiscale" del tab "Corrispettivi"
	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var reject = 0;
				var discriminator = ["fiscalCheckPerson", "fiscalCheckTariff", "fiscalCheckVatCode", "fiscalCheckNotes"];
				var column = ["person","string","string","string"];
				columnLen = column.length;
				var value = [];
				for (i = 0; i < columnLen; i++) {
					if(Packages.java.lang.Boolean.TRUE.equals(Packages.it.cilea.wf.util.WfUtil.isAttributeChanged(wfService, wfItem, column[i]+ "." +discriminator[i]))){
						reject = 1;
						break;
					}
				}
				if(reject > 0){
					errors.reject("error.contract.fiscalCheck.edit.notAllowed");
				}
			}		
		

wfActionLogicEnterEquipmentOwnerMailSender

			X={
			subjectLabel:'label.ap.equipment.mail.subject',
			textLabel:'label.ap.equipment.mail.text',
			sendEnable:'ap.itemType.eqp.mail.enable',
			htmlEnable:'ap.itemType.eqp.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleOwners',
			to:'',
			from:''
			}; X;
		

wfActionLogicEnterEquipmentHeadOfDepartmentMailSender

			X={
			subjectLabel:'label.ap.equipment.mail.subject',
			textLabel:'label.ap.equipment.mail.text',
			sendEnable:'ap.itemType.eqp.mail.enable',
			htmlEnable:'ap.itemType.eqp.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleHeadOfDepartment',
			to:'',
			from:''
			}; X;
		

wfActionLogicCreateRmItem

			function createNewOrgUnitElementEquipment(department, rmItem){
				
				var orgUnitElement= Packages.it.cilea.ga.model.OrganizationUnitElement();
				
				orgUnitElement.setDiscriminator("equipment");
				orgUnitElement.setOrganizationUnit(department);
				orgUnitElement.setOrganizationUnitId(department.getOrganizationUnitId());
				orgUnitElement.getRmItemMap().put("equipment", rmItem);
				
				return orgUnitElement;
			}
			
			//log.error("Sono nella action //logic di enter wfAction//logicCreateRmItem -updated");
			
			var wfItem= wfService.getWfItem(object.getId());
			var rmItemMap=wfItem.getRmItemMap();
			var rmItem=rmItemMap.get("equipment");
			
			if(rmItem==null){
				rmItem= Packages.it.cilea.ga.model.RmItem();
				
				var today = new Date();
				rmItem.setCreateDate(today);
				
				rmItem.setRmItemTypeId(10);
				
				rmItem.getIntegerMap().put("apItemSourceId", object.getId());
			}
			rmItem.setDescription(wfItem.getDescription());
			rmItem.getStringMap().put("apItemSourceIdentifier", object.getIdentifier());
			
			//aggiungo o sovrascrivo l'rmItem
			rmItemMap.put("equipment", rmItem);
			//sovrascrivo la mappa, ci metto quella aggiornata
			wfItem.setRmItemMap(rmItemMap);
			
			//mi tengo da parte l'id prima del salvataggio
			//lo userò dopo per vedere se devo cercare orgUnitElement
			var rmItemId=rmItem.getId();
			
			//log.error("rmItemId prima del salvataggio: "+rmItemId);
			
			//salvo
			gaService.saveOrUpdate(rmItem);
			wfService.saveOrUpdate(wfItem);
			//log.error("Salvato rmItem e wfItem");
			
			
			//PARTE PER AGGIUNTA AL DIPARTIMENTO
			
			//prima tolgo tutti gli orgUnitElement, se ce ne sono attaccati all'rmItem
			//poi li riaggiungo tutti
			
			if(rmItemId!=null){
				//log.error("rmItem non nuovo");
				
				var paramMap = new Packages.java.util.HashMap();
				paramMap.put("rmItemValueId", rmItem.getId());	
				var orgUnitElementList=searchBuilderTemplate.query("getOrganizationUnitElementByRmItemId", paramMap);
				
				var orgUnitElementListIter= orgUnitElementList.iterator();
				while(orgUnitElementListIter.hasNext()){
					var orgUnitElement=orgUnitElementListIter.next();
					gaService.deleteOrganizationUnitElement(orgUnitElement.getId());
					//log.error("Eliminato orgUnitElement con id: "+orgUnitElement.getId());
				}
			}
			
			/*
			var paramMap = new Packages.java.util.HashMap();
			paramMap.put("rmItemValueId", 10);			
			var orgUnitList=searchBuilderTemplate.query("getOrganizationUnitElementByRmItemId", paramMap);
			*/
			
			var departmentSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);
			var departmentSetIterator = departmentSet.iterator();
			
			while(departmentSetIterator.hasNext()){
				
				var departmentElement=departmentSetIterator.next();
				var departmentEmpty= departmentElement.getOrganizationUnitMap().get("ouId");
				var department=gaService.getOrganizationUnit(departmentEmpty.getId());
				//log.error("Dipartimento: "+department.getDescription());
				
				//a differenza della versione di prima, so già che non ci sono orgUnitElement attaccati al mio rmItem
				//quindi ne aggiungo direttamente uno
				
				department.getOrganizationUnitElementSet().add(
						createNewOrgUnitElementEquipment(department, rmItem)
					);
				//log.error("Aggiunto nuovo orgUnitElement");
				
				gaService.saveOrUpdate(department);
				//log.error("Salvato il dipartimento");
			}
			
			
			//log.error("fine action di enter");
			
			
			
		

wfActionLogicEnterLaboratoryOwnerMailSender

			X={
			subjectLabel:'label.ap.laboratory.mail.subject',
			textLabel:'label.ap.laboratory.mail.text',
			sendEnable:'ap.itemType.lab.mail.enable',
			htmlEnable:'ap.itemType.lab.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleOwners',
			to:'',
			from:''
			}; X;
		

wfActionLogicEnterLaboratoryHeadOfDepartmentMailSender

			X={
			subjectLabel:'label.ap.laboratory.mail.subject',
			textLabel:'label.ap.laboratory.mail.text',
			sendEnable:'ap.itemType.lab.mail.enable',
			htmlEnable:'ap.itemType.lab.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleHeadOfDepartment',
			to:'',
			from:''
			}; X;
		

equipmentValidatorLaboratory
Validazione che controlla che se esiste almeno una Grande Attrezzatura collegata al Laboratorio, questa Attrezzatura deve essere in stato "Approved" , altrimenti lancia un errore.
Dal punto di vista del modello dati si tratta degli elementi di tipo laboratoryEquipmentLink
Per maggiori dettagli cfr. excel modello dati dell'entità Gruppi di Lavoro

		//log.error("entro nel validator");
		var equipmentSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getChildWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "laboratoryEquipmentLink", wfService);
		
		//log.error("equipmentSet size= "+equipmentSet.size());
		if(equipmentSet.size()>0){
			var equipmentSetIterator = equipmentSet.iterator();
			while (equipmentSetIterator.hasNext()) {
				var equipmentElement = equipmentSetIterator.next();
			    var equipment = equipmentElement.getChild();
			    var equipmentState = equipment.getWfState().getDescription();
			    //log.error("stato dell'equipment"+equipmentState);
			    if(!Packages.org.apache.commons.lang.StringUtils.equals("approved", equipmentState)){
			    	//log.error("trovato un laboratory non approvato");
			    	errors.reject("error.laboratory.equipment.mustBeApproved");
			    }
			}
		 }		 
  		

wfActionLogicCreatePersonElementIncoming

			
			function obtainIncomingTypeDictionary(incomingTypeDescription){
				//prima di tutto ne cerco
				var incomingTypeDictionaryList = gaService.getGaDictionarySearchList(incomingTypeDescription, "incomingType", null, null, null);
				
				//se non ne trovo allora creo da zero il dizionario, lo salvo e lo restituisco
				if(incomingTypeDictionaryList.size()==0){
					var newIncomingTypeDictionary = Packages.it.cilea.ga.model.GaDictionary();
					newIncomingTypeDictionary.setDescription(incomingTypeDescription);
					newIncomingTypeDictionary.setDiscriminator("incomingType");
					//newIncomingTypeDictionary.setId(gaService.saveOrUpdate(newIncomingTypeDictionary));
					newIncomingTypeDictionary.getStringMap().put("MANAGED_BY", "system");	//in modo tale che non possa essere modificato da interfaccia
					gaService.saveOrUpdate(newIncomingTypeDictionary);
					return newIncomingTypeDictionary;
				}else{	//altrimenti lo restituisco direttamente
					//non vado a ciclare tutta la lista, ne ho solo uno di dictionary fatto così
					return incomingTypeDictionaryList.get(0);
				}
				
			}
		
			//log.error("wfActionLogicCreatePersonElementIncoming");
			
			var wfItem = wfService.getWfItem(object.getId());
			var wfItemId = wfItem.getId();
			var wfItemIdentifier = wfItem.getIdentifier();

			//poi vado a ricavare tutti i tutor inseriti
			var tutorWfItemElementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement","tutor", wfService);

			//solo se ne trovo, allora eseguo il resto della procedura			
			if(!tutorWfItemElementSet.isEmpty()){
			
				//ora vado a ciclare ogni wfItemElement, ricavando poi la persona collegata
				var tutorWfItemElementSetIterator = tutorWfItemElementSet.iterator();
				while(tutorWfItemElementSetIterator.hasNext()){
				
					var tutorWfItemElement = tutorWfItemElementSetIterator.next();
					
					var tutorPerson = tutorWfItemElement.getPersonMap().get("contributorId");	//restituisce la person completa?
					tutorPerson = gaService.getPerson(tutorPerson.getId());	//nel dubbio la ricavo dal service
					
					//ora che ho la persona, ne vado a ricavare gli element di incoming che mi servono
					var incomingPersonElementSet = tutorPerson.getPersonElementSet("incoming");
					var incomingPersonElementSetIterator = incomingPersonElementSet.iterator();

					
					//vado a ciclare il set per vedere se quell'element esiste già
					//se esiste già, lo rimuovo
					//e dopo ne aggiungo uno nuovo nuovo appena creato
					while(incomingPersonElementSetIterator.hasNext()){
						
						var  incomingPersonElement = incomingPersonElementSetIterator.next();

						var  incomingPersonElementSourceIdentifier = incomingPersonElement.getStringMap().get("apItemSourceIdentifier");
						var  incomingPersonElementSourceId = incomingPersonElement.getIntegerMap().get("apItemSourceId");
						
						//doppio controllo, così gestisco il caso in cui l'item non abbia un identifier come può succedere se proviene da tabelle di frontiera
						if(Packages.org.apache.commons.lang.StringUtils.equals(wfItemIdentifier, incomingPersonElementSourceIdentifier) || (wfItemId==incomingPersonElementSourceId) ){
						
							//lo sgancio dalla persona, lo elimino e salvo la persona
							tutorPerson.getPersonElementSet().remove(incomingPersonElement);
							gaService.deletePersonElement(incomingPersonElement.getId());
							gaService.saveOrUpdate(tutorPerson);
							//log.error("delete old personelement");
						}
					}

					//ora che mi sono accertato che per certo non ho quel personElement, me ne vado a creare uno completamente nuovo ed aggiornato
					//log.error("new person element");
					var newPersonElementIncoming = new Packages.it.cilea.ga.model.PersonElement();
					
					//ed ora passo ad agganciarci tutte le informazioni che gli servono
					newPersonElementIncoming.setPersonId(tutorPerson.getPersonId());
					//newPersonElementIncoming.setPerson(tutorPerson);
					newPersonElementIncoming.setDiscriminator("incoming");
					newPersonElementIncoming.getPersonMap().put("tutoree", wfItem.getPersonMap().get("owner"));
					
					//visto che il miurExternalOrganization è un element ma unico, ricavo il primo elemento e da lì il tutto
					var miurExternalOrganizationUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement","miurExternalOrganization", wfService);
					
					//controllo ulteriore nel caso in cui cambino le validazioni e non sia più obbligatorio
					if(!miurExternalOrganizationUnitSet.isEmpty()){
					
						var miurExternalOrganizationUnit = miurExternalOrganizationUnitSet.iterator().next().getOrganizationUnitMap().get("externalOrganization");
						newPersonElementIncoming.getOrganizationUnitMap().put("miurExternalOrganization", miurExternalOrganizationUnit);
					}
					
					newPersonElementIncoming.getStringMap().put("apItemSourceIdentifier", wfItemIdentifier);
					newPersonElementIncoming.getIntegerMap().put("apItemSourceId", wfItemId);
					
					if(tutorWfItemElement.getDateMap().get("startDate")!=null)
						newPersonElementIncoming.getDateMap().put("startDate", tutorWfItemElement.getDateMap().get("startDate"));
					if(tutorWfItemElement.getDateMap().get("endDate")!=null)
						newPersonElementIncoming.getDateMap().put("endDate", tutorWfItemElement.getDateMap().get("endDate"));
					
					//gestione dictionary
					var incomingTypeDescription = wfItem.getWfItemType().getDescription();
					var incomingTypeDictionary = obtainIncomingTypeDictionary(incomingTypeDescription);
					newPersonElementIncoming.getDictionaryMap().put("incomingType", incomingTypeDictionary);
					
					//aggiungo metadato per marcare come è stato gestito
					newPersonElementIncoming.getStringMap().put("managedBy", "system");
					
					//ora che è completo, vado a salvarlo
					gaService.saveOrUpdate(newPersonElementIncoming);
					
					//lo aggiungo alla person e salvo la person
					tutorPerson.getPersonElementSet().add(newPersonElementIncoming);
					gaService.saveOrUpdate(tutorPerson);
					//log.error("Saved person");
	
				}//tutorWfItemElementSetIterator
				
			}//fine tutorWfItemElementSet.isEmpty
			
		

deleteAllPersonElementsLinkedToMobility
Logica che si occupa di andare ad eliminare tutti i collegamento delle persone alla Mobilità in ingresso di cui erano supervisore
E' una logica che viene triggerata in fase di DELETE di una Mobility Incoming (Mobilità in ingresso).

		
			//log.error("deleteAllPersonElementsLinkedToMobility");
			
			var wfItem = wfService.getWfItem(object.getId());
			var wfItemId = wfItem.getId();
			var wfItemIdentifier = wfItem.getIdentifier();

			var tutorWfItemElementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement","tutor", wfService);
		
			if(!tutorWfItemElementSet.isEmpty()){
			
				var tutorWfItemElementSetIterator = tutorWfItemElementSet.iterator();
				
				while(tutorWfItemElementSetIterator.hasNext()){
				
					var tutorWfItemElement = tutorWfItemElementSetIterator.next();
					
					var tutorPerson = tutorWfItemElement.getPersonMap().get("contributorId");	//restituisce la person completa?
					tutorPerson = gaService.getPerson(tutorPerson.getId());	//nel dubbio la ricavo dal service
					
					var incomingPersonElementSet = tutorPerson.getPersonElementSet("incoming");
					var incomingPersonElementSetIterator = incomingPersonElementSet.iterator();
					
					//vado a ciclare il set per vedere se quell'element esiste già
					//se esiste già, lo rimuovo
					while(incomingPersonElementSetIterator.hasNext()){
						
						var incomingPersonElement = incomingPersonElementSetIterator.next();

						var incomingPersonElementSourceIdentifier = incomingPersonElement.getStringMap().get("apItemSourceIdentifier");
						var incomingPersonElementSourceId = incomingPersonElement.getIntegerMap().get("apItemSourceId");
						
						//doppio controllo, così gestisco il caso in cui l'item non abbia un identifier come può succedere se proviene da tabelle di frontiera
						if(Packages.org.apache.commons.lang.StringUtils.equals(wfItemIdentifier, incomingPersonElementSourceIdentifier) || (wfItemId==incomingPersonElementSourceId) ){
							
							tutorPerson.getPersonElementSet().remove(incomingPersonElement);
							gaService.deletePersonElement(incomingPersonElement.getId());
							gaService.saveOrUpdate(tutorPerson);
							//log.error("delete old personelement");
						}
					}
				}//tutorWfItemElementSetIterator
			}//fine tutorWfItemElementSet.isEmpty
			
		

deletePersonElementFromOldTutor
Logica che si occupa di andare ad eliminare il collegamento delle persone alla Mobilità in ingresso di cui erano supervisori (tutor)
E' una logica che viene triggerata in fase di SAVE della Mobility Incoming (Mobilità in ingresso).

			
			//log.error("Inside deletePersonElementFromOldTutor");
		
			var wfItem = wfService.getWfItem(object.getId());
			var wfItemId = wfItem.getId();
			var wfItemIdentifier = wfItem.getIdentifier();
			
			//ricavo i vecchi tutor memorizzati su db
			var tutorApItemElementSetOLD = wfItem.getWfItemElementSet("tutor");
			//ricavo i tutor aggiornati dal fragment
			var tutorApItemElementSetNEW = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement","tutor", wfService);
			
			//ciclo quelli ricavati dal DB per andare a ricavare quelli che sono stati eliminati
			var tutorApItemElementSetOLDIterator = tutorApItemElementSetOLD.iterator();
			
			while(tutorApItemElementSetOLDIterator.hasNext()){
				
				//log.error("inside old tutor set");
			
				//if(tutorApItemElementSetOLDIterator != null){
					var tutorApItemElement = tutorApItemElementSetOLDIterator.next();
				
					if(!tutorApItemElementSetNEW.contains(tutorApItemElement)){
					
						//log.error("Found old tutor");
					
						var tutorPerson = tutorApItemElement.getPersonMap().get("contributorId");
						tutorPerson = gaService.getPerson(tutorPerson.getId());
						
						//log.error("is: " + tutorPerson.getDisplayValue());
						
						var incomingPersonElementSet = tutorPerson.getPersonElementSet("incoming");
						var incomingPersonElementSetIterator = incomingPersonElementSet.iterator();
						
						while(incomingPersonElementSetIterator.hasNext()){
						
							//log.error("inside incoming set of tutor");
							
							var incomingPersonElement = incomingPersonElementSetIterator.next();
							
							var incomingPersonElementSourceIdentifier = incomingPersonElement.getStringMap().get("apItemSourceIdentifier");
							var incomingPersonElementSourceId = incomingPersonElement.getIntegerMap().get("apItemSourceId");
							
							if( Packages.org.apache.commons.lang.StringUtils.equals(wfItemIdentifier, incomingPersonElementSourceIdentifier) || 
								(wfItemId == incomingPersonElementSourceId) ){
								
								tutorPerson.getPersonElementSet().remove(incomingPersonElement);
								
								gaService.deletePersonElement(incomingPersonElement.getId());
								
								gaService.saveOrUpdate(tutorPerson);
								//log.error("deleted old personelement and person saved");
							}
						}
					}
				//}else{
					//log.error("tutorApItemElementSetOLDIterator IS NULL");
				//}
			}
			
		

wfStartLogicPatent

			var applicationNumber=wfItem.getStringMap().get("applicationNumber");
			wfItem.setIdentifier(applicationNumber);
			
			var applicationDate=wfItem.getDateMap().get("applicationDate");
			var year=applicationDate.get(Packages.java.util.Calendar.YEAR);
			wfItem.setYear(year);
			
			if(Packages.java.lang.Boolean.FALSE.equals(wfItem.getBooleanMap().get("recoveryMetadataFromEPO"))){
				var linkedInventionId = wfItem.getIntegerMap().get("linkedInventionId");
			
				var linkedInvention = wfService.getWfItem(linkedInventionId);
				
				var inventionIprLink = new Packages.it.cilea.wf.model.WfItemLink();
				
				inventionIprLink.setParentId(linkedInventionId);
				inventionIprLink.setChildId(wfItem.getId());
				inventionIprLink.setDiscriminator("inventionIprLink");
				
				var parentWfItemLinkSet = wfItem.getParentWfItemLinkSet();
				parentWfItemLinkSet.add(inventionIprLink);
				wfItem.setParentWfItemLinkSet(parentWfItemLinkSet);
								
				wfItem.getIntegerMap().put("linkedInventionId", null);				
				wfService.saveOrUpdate(inventionIprLink);				
			}
			wfService.saveOrUpdate(wfItem);
			
		

wfActionLogicSaveRPDFV3Evaluation

it.cilea.wf.surplus.logic.action.save.rpdf.WfActionLogicSaveRPDFV3Evaluation

wfStartLogicProjectDepartmentFundYear

					
				var year = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("DEPARTMENT_FUND_YEAR");			
				wfItem.setYear(new Packages.java.lang.Integer(year));			
				true;
			

wfStartLogicProjectDepartmentFundPositionLastDate

		
				if(wfItem.getOrganizationUnitMap().get("department") == null){		
					var positionlastDate = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("DEPARTMENT_FUND_POSITION_LAST_DATE");
					//25/02/2019
					var lastYear = positionlastDate.substring(6, 10);
					var intLastYear = parseInt(lastYear);
					var positionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
					positionSearch.setPersonId(wfItem.getPersonMap().get("owner").getId());
					positionSearch.setYear(intLastYear);
					positionSearch.setOrganizationUnitTypeDescription("department");
					var positionList = gaService.getPositionSearchList(positionSearch, 0);
					var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionList, null, positionSearch.getOrganizationUnitTypeDescription());		
					var positionListIterator=positionList.iterator();							
					while (positionListIterator.hasNext()){
						var position = positionListIterator.next();
						if (maxPriority==null || maxPriority.equals(position.getPriority())){
							wfItem.getOrganizationUnitMap().put("department", position.getOrganizationUnit());
						}
					}
				}				
				true;
			

projectDepartmentFundCreateValidator

			var configurationStart = "DEPARTMENT_FUND_START_DATE";
			var configurationEnd = "DEPARTMENT_FUND_END_DATE";
			var startDate = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue(configurationStart);
			var endDate = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue(configurationEnd);
			var formatter = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			var now = new java.util.Date();			
			var ateStart = formatter.parse(startDate);
			var ateEnd = formatter.parse(endDate);
			if(!(now.after(ateStart) && now.before(ateEnd))){			
				errors.reject("error.operation.notallowed");
			}
		

projectDepartmentFundTeamValidator

			if(object.getPersonMap().get("owner") != null){
				var findUser = 0;
				var ownerId = object.getPersonMap().get("owner").getId();
				var userSet = gaService.getPerson(ownerId).getUserSet()
				userSetIterator = userSet.iterator();											
				while (userSetIterator.hasNext()){
					var user = userSetIterator.next();	
					var userId = user.getId();
					var searchCommand = new Packages.it.cilea.ga.command.TeamUserLinkSearchCommand();
					searchCommand.setUserId(userId);
					var linkList = gaService.getTeamUserLinkSearchList(searchCommand, 0);
					var listIterator = linkList.iterator();				
					while(listIterator.hasNext()){
						var teamUserLink = listIterator.next();	
						var teamId = teamUserLink.getTeamId();
						if(teamId == Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.departmentFund.team.start")){
							findUser = 1;
							break;
						}
					}
					if(findUser == 1){
						break;
					}
				}	
				if(findUser == 0){
					errors.reject("error.start.position.departmentFund", [Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("DEPARTMENT_FUND_POSITION_LAST_DATE")], null);	
				}
			}
		

projectDepartmentFundCheckDateEnterValidator

	
			var gaUserDetail = Packages.it.cilea.ga.authorization.context.GaAuthorizationUserHolder.getUser();	
			if (!"ROLE_ADMIN".equals(gaUserDetail.getCurrentAuthorityIdentifier())){
				var state = wfItem.getWfState().getDescription();
				var configurationKeyStart = "DEPARTMENT_FUND_STATE_START_DATE_" + state.toUpperCase();
				var configurationKeyEnd = "DEPARTMENT_FUND_STATE_END_DATE_" + state.toUpperCase();
				var stateStartDate = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue(configurationKeyStart);
				var stateEndDate = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue(configurationKeyEnd);
				var formatter = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				var now = new java.util.Date();			
				var start = formatter.parse(stateStartDate);
				var end = formatter.parse(stateEndDate);
				if(!(now.after(start) && now.before(end))){			
					errors.reject("error.operation.notallowed");
				}	
			}	
		

isNotLegacyAndYearIsGreaterOrEqualThan2019Project
Questa è un'applicability rule che viene valutata prima di eseguire altre validazioni.
Se ritorna true allora vengono eseguite le altre validazioni altrimenti no.
Oltre al check previsto da isNotLegacy , verifica anche che il progetto in questione sia relativo ad un anno maggiore o uguale del 2019, altrimenti vengono disattivate le validazioni e le sincronizzazioni.
Questo approccio è stao scelto per evitare lo scatenarsi delle validazioni su vecchi progetti che non rispettano le nuove e più stringenti validazioni, ed evitare quindi di dovere fare una bonifica a tappeto.

			log.error("Sono in isNotLegacyAndYearIsGreaterOrEqualThan2019Project");
			(
				object.getYear()!=null 
				&& 
				object.getYear().compareTo(2019)>=0
			) 
			&& 
			(
				object.getBooleanMap().get('legacy')==null 
				|| 
				Packages.java.lang.Boolean.FALSE.equals(object.getBooleanMap().get('legacy'))
			)
		

wfStartLogicProject
Questa logica viene eseguita in fase di creazione di un nuovo progetto.
Vengono effettuate le seguenti operazioni:

Per maggiori dettagli cfr. excel modello dati dell'entità Progetto
							
				var person = null;
				var startDate = wfItem.getDateMap().get("proposalStartDate");
			    person = wfItem.getPersonMap().get("owner");
				var person2 = gaService.getPerson(person.getId());
				var ownerElement = new Packages.it.cilea.wf.model.WfItemElement();
				ownerElement.setDiscriminator("owner");
				ownerElement.setWfItemId(wfItem.getId());
				ownerElement.getPersonMap().put("ownerId", person);
				
				if (Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.prj.owner.role.enabled").equalsIgnoreCase("true")){
				 	var myRole = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.prj.owner.role.main");
					if (myRole == null){
						throw "Configuration variables ap.prj.owner.role.main MUST BE DEFINED";
					} else {
						var ownerRole = wfService.getWfDictionary(new Packages.java.lang.Integer(myRole));
						ownerElement.getWfDictionaryMap().put("roleId", ownerRole);
					}
				}
				
				var ownerStartDateDefault = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.ownerStartDate.default");
				if(ownerStartDateDefault != null && "true".equals(ownerStartDateDefault)){
					ownerElement.getDateMap().put("startDate", startDate);
				}
				
				wfService.saveOrUpdate(ownerElement);
				wfItem.getWfItemElementSet().add(ownerElement);
				
				var positionLastSet = person2.getPositionLastSet();
				var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionLastSet, "research", "department");
				//var maxPriority2 = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionSet, "research", "academicField2000");
				
				
				positionLastSetIterator = positionLastSet.iterator();
				while (positionLastSetIterator.hasNext()){
					var position = positionLastSetIterator.next();
					if (maxPriority == null || maxPriority.equals(position.getPriority())) {
						if ("research".equals(position.getDiscriminator()) && "department"
									.equals(position.getOrganizationUnit().getOrganizationUnitType().getDescription())) {
							var internalOrganizationUnitElement = new Packages.it.cilea.wf.model.WfItemElement();
							internalOrganizationUnitElement.setDiscriminator("internalOrganizationUnit");
							internalOrganizationUnitElement.setWfItemId(wfItem.getId());
							var internalOrganizationUnitRoleId = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.internalOrganizationUnit.role.main");
							var internalOrganizationUnitRole = wfService.getWfDictionary(new Packages.java.lang.Integer(internalOrganizationUnitRoleId));
							internalOrganizationUnitElement.getOrganizationUnitMap().put("ouId", position.getOrganizationUnit());
							internalOrganizationUnitElement.getWfDictionaryMap().put("ouRole", internalOrganizationUnitRole);
							wfService.saveOrUpdate(internalOrganizationUnitElement);
							wfItem.getWfItemElementSet().add(internalOrganizationUnitElement);
							break;
						}
					}
				}
				
				//partner
				var uniquePartnerRoleId = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.role.uniquePartner");
				var myOrganization = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.myOrganization");
				if (uniquePartnerRoleId == null || myOrganization == null){
					throw "Configuration variables ap.project.partner.role.uniquePartner and ap.project.partner.myOrganization MUST BE DEFINED";
				} else {
					uniquePartnerRoleId = wfService.getWfDictionary(new Packages.java.lang.Integer(uniquePartnerRoleId));
					myOrganization = gaService.getOrganizationUnit(new Packages.java.lang.Integer(myOrganization));
					var partnerElement = new Packages.it.cilea.wf.model.WfItemElement();
					partnerElement.setDiscriminator("partner");
					partnerElement.setWfItemId(wfItem.getId());
					partnerElement.getOrganizationUnitMap().put("partnerId", myOrganization);
					partnerElement.getWfDictionaryMap().put("partnerRole", uniquePartnerRoleId);
					wfService.saveOrUpdate(partnerElement);
				}
				
				
				wfItem.getPersonMap().put("owner", null);
				var year = startDate.get(Packages.java.util.Calendar.YEAR);
				wfItem.setYear(new Packages.java.lang.Integer(year));
				true;
			

wfActionLogicEnterProjectOwnerMailSender

			X={
			subjectLabel:'label.ap.project.mail.subject',
			textLabel:'label.ap.project.mail.text',
			sendEnable:'ap.project.mail.enable',
			htmlEnable:'ap.project.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleOwners',
			to:'',
			from:''
			}; X;
		

wfActionLogicEnterProjectContributorMailSender

			X={
			subjectLabel:'label.ap.project.mail.subject',
			textLabel:'label.ap.project.mail.text',
			sendEnable:'ap.project.mail.enable',
			htmlEnable:'ap.project.mail.html.enable',
			identityLogic:'wfIdentityLogicContributor',
			to:'',
			from:''
			};X;
		

wfActionLogicEnterProjectHeadOfDepartmentMailSender

			X={
			subjectLabel:'label.ap.project.mail.subject',
			textLabel:'label.ap.project.mail.text',
			sendEnable:'ap.project.mail.enable',
			htmlEnable:'ap.project.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleHeadOfDepartment',
			to:'',
			from:''
			};X;
		

wfActionLogicEnterProjectMailSender

			var mailEnableParam = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.mail.enable");
			var mailHtmlEnableParam = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.mail.html.enable");
			var isHtml;
			if(mailHtmlEnableParam.equalsIgnoreCase("true")){
				isHtml = true;
			}
			else{
				isHtml = false;
			}
			if (mailEnableParam!=null && mailEnableParam.equalsIgnoreCase("true")){
				var wfItemIdentifier = wfItem.getIdentifier();
				var wfItemDescription = wfItem.getDescription();
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				var ownerSetIterator=ownerSet.iterator();
				while(ownerSetIterator.hasNext()){
					var ownerElement=ownerSetIterator.next();
					var person = ownerElement.getPersonMap().get("ownerId");
					person = gaService.getPerson(person.getId());
					var contact=person.getPrincipalContactMap().get("mail");
					var surnameName = person.getLastName()+" "+person.getFirstName();
					var subjectLabel=messageUtil.findMessage("label.ap.project.mail.subject", [wfItemIdentifier]);
					var textLabel=messageUtil.findMessage("label.ap.project.mail.text",[wfItemIdentifier, surnameName, wfItemDescription, wfItem.getWfState().getDisplayValue()]);
					mailService.send("no-reply@cineca.it", [contact], null, null, subjectLabel, textLabel, null, isHtml);
				}
			}
		

wfUgovPjSenderValidatorProject
Questa logica, effettua check di consistenza sulle mappature degli oggetti IRIS/UGOV e, se superati, invia il progetto verso UGOV PJ rispettando le regole di NON SOVRASCRITTURA lato UGOV PJ.
Per maggiori dettagli su queste regole consultare il team di UGOV PJ.
Le controparti dei progetti IRIS vengono create su UGOV con le regole di mappature delle tassonomie che vengono condivise in fase di attivazione.
Se in corso d'opera dovesse nascere l'esigenza di censire delle nuove tipologie è possibile contattare l'HD.
Di seguito vengono riportate le informazioni inviate ad UGOV PJ, con la specifica dell'attributo del modello dell'entità Progetto IRIS


Per maggiori dettagli cfr. excel modello dati dell'entità Progetto
			var Logic = function(wfItem, dtoPj, superLogic, errors, messageUtil, request, gaService, wfService, wfTaskService, searchBuilderTemplate, log) {
			this.wfItem=wfItem;
			this.dtoPj=dtoPj;
			this.superLogic=superLogic;
			this.errors=errors;
			this.messageUtil=messageUtil;
			this.request=request;
			this.gaService=gaService;
			this.wfService=wfService;
			this.wfTaskService=wfTaskService;
			this.searchBuilderTemplate=searchBuilderTemplate;
			this.log=log;
			this.setInternalOrgUnitList = function() {
				var internalOrganizationUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);
				var internalOrganizationUnitSetIterator=internalOrganizationUnitSet.iterator();
				while (internalOrganizationUnitSetIterator.hasNext()){
					var element=internalOrganizationUnitSetIterator.next();
					var orgUnit = element.getOrganizationUnitMap().get("ouId");
					var orgUnitRole = element.getWfDictionaryMap().get("ouRole");
					dtoPj.getDTOUoPjs().add(superLogic.getOrganizationUnit(orgUnit, orgUnitRole, errors));
				}
			};			
			this.setFinanciers = function() {
				var sendGrantor2Ugov=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.grantor.send2ugov.enable");
				if (sendGrantor2Ugov && sendGrantor2Ugov.trim().equalsIgnoreCase("true")){
					var contractorSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement", "grantor",wfService);
					var contractorSetIterator=contractorSet.iterator();
					while (contractorSetIterator.hasNext()){
						var element=contractorSetIterator.next();
						var organizationUnit = element.getOrganizationUnitMap().get("grantorId");
						var enteFinanziatore = superLogic.getEnteFinanziatore(organizationUnit, this.getFinancing(), contractorSet.size(), errors);
						dtoPj.getDTOEfPjs().add(enteFinanziatore);
					}
				}
			};
			this.setPartners = function() {
				var sendPartner2Ugov=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.send2ugov.enable");
				if (sendPartner2Ugov && sendPartner2Ugov.trim().equalsIgnoreCase("true")){
					var partnerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement", "partner",wfService);
					var partnerSetIterator=partnerSet.iterator();
					while (partnerSetIterator.hasNext()){
						var element=partnerSetIterator.next();
						var organizationUnit = element.getOrganizationUnitMap().get("partnerId");
						var partnerRole = element.getWfDictionaryMap().get("partnerRole");
						var partecipante = superLogic.getPartecipante(organizationUnit,  partnerRole, errors);
						dtoPj.getDTOPartPjs().add(partecipante)
					}
				}			
			};
			this.getFinancing = function() {
				var coordinatorRoleId=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.role.main");
				var myOrganization=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.myOrganization");
				var forcedPjInternalCost=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.financing.internalCost.send2ugov.forced");
				if (forcedPjInternalCost==null)
					forcedPjInternalCost=false;
				else if (forcedPjInternalCost.equalsIgnoreCase("true")){				
					forcedPjInternalCost=true;
				} else {
					forcedPjInternalCost=false;
				}
				
				if (!forcedPjInternalCost){
					if (coordinatorRoleId==null || myOrganization==null){
						throw "Configuration variables ap.project.partner.role.main and ap.project.partner.myOrganization MUST BE DEFINED";
					} else {
						coordinatorRoleId=new Packages.java.lang.Integer(coordinatorRoleId);
						myOrganization=new Packages.java.lang.Integer(myOrganization);
					}		
					var partnerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement", "partner",wfService);
					var partnerSetIterator=partnerSet.iterator();
					while (partnerSetIterator.hasNext()){
						var element=partnerSetIterator.next();			 
						var orgUnitRole = element.getWfDictionaryMap().get("partnerRole");
						if (orgUnitRole==null){
							errors.reject("error.project.partner.missingRole");
							throw "Detected partner without role";
						}
						
						var orgUnit = element.getOrganizationUnitMap().get("partnerId");
						if(myOrganization.equals(orgUnit.getId()) && coordinatorRoleId.equals(orgUnitRole.getId())){				
							var globalCost=wfItem.getNumberMap().get("globalCost");
							if (globalCost==null)
								globalCost=Packages.java.math.BigDecimal.ZERO;
							
							var globalContribution=wfItem.getNumberMap().get("globalContribution");
							if (globalContribution==null)
								globalContribution=Packages.java.math.BigDecimal.ZERO;
							
							var internalCofinancing=wfItem.getNumberMap().get("internalCofinancing");
							if (internalCofinancing==null)
								internalCofinancing=Packages.java.math.BigDecimal.ZERO;
							
							return globalCost.subtract(globalCost.subtract(globalContribution).subtract(internalCofinancing));
						}			
					}
				}				
				return wfItem.getNumberMap().get("internalCost");
			};
			this.getStartDate = function() {
				var expenditureDateEnabled=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.date.expenditure.send2ugov.enabled");
				if (expenditureDateEnabled && expenditureDateEnabled.trim().equalsIgnoreCase("true")){
					if (wfItem.getDateMap().get("expenditureStartDate")!=null)
						return wfItem.getDateMap().get("expenditureStartDate");
					else
						return wfItem.getDateMap().get("startDate");
				} else {
					return wfItem.getDateMap().get("startDate");
				}							    	
			};
			this.getEndDate = function() {
				var expenditureDateEnabled=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.date.expenditure.send2ugov.enabled");
				if (expenditureDateEnabled && expenditureDateEnabled.trim().equalsIgnoreCase("true")){
					if (wfItem.getDateMap().get("expenditureEndDate")!=null)
						return wfItem.getDateMap().get("expenditureEndDate");
					else
						return wfItem.getDateMap().get("endDate");
				} else {
					return wfItem.getDateMap().get("endDate");
				}		
			};
			this.getIdentifier = function() {	
				return wfItem.getIdentifier();
			};
			this.getDescription = function() {
				if(wfItem.getDescription()!=null){
					var length=wfItem.getDescription().length();
					return wfItem.getDescription().substring(0,(length>255)?255:length);
				} else {
					return null;
				}
			};
			this.getCup = function() {
				var sendCup2Ugov = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.cup.send2ugov.enable");
				if (sendCup2Ugov && sendCup2Ugov.trim().equalsIgnoreCase("true")){
					return wfItem.getStringMap().get("cup");
				} else {
					return null;
				}				
			};
			this.getAcronym = function() {
				return wfItem.getStringMap().get("acronym");
			};
			this.getExternalDmsIdentifier = function() {
				return wfItem.getStringMap().get("externalDmsIdentifier");
			};
			this.isSynchronizable = function() {
				var legacy=wfItem.getBooleanMap().get("legacy");
				var financing=this.getFinancing();				
				if (Packages.java.lang.Boolean.TRUE.equals(legacy) || financing==null || Packages.java.math.BigDecimal.ZERO.equals(financing))
					return Packages.java.lang.Boolean.FALSE;
				else			    
					return Packages.java.lang.Boolean.TRUE;
			};
			this.getProjectType = function() {
				return superLogic.getProjectType(wfItem);
			};
			this.getFinanceSchema = function() {
				return this.getProjectType();
			};
			this.getPjInternalCode = function() {
				return null;
			};
			this.isContributorStartDateRequired = function() {						
				var contributorStartDateRequired=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.contributor.starDate.required");
				if (contributorStartDateRequired){
					if (contributorStartDateRequired.trim().equalsIgnoreCase("true")){
						return Packages.java.lang.Boolean.TRUE;
					} else if (contributorStartDateRequired.trim().equalsIgnoreCase("false")){
						return Packages.java.lang.Boolean.FALSE;
					} else {
						throw "ap.project.contributor.starDate.required MUST BE true or false";
					}
				} else {
					return Packages.java.lang.Boolean.TRUE;
				}							    
			};				
			this.isOwnerStartDateRequired = function() {
				var ownerStartDateRequired=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.owner.starDate.required");
				if (ownerStartDateRequired){
					if (ownerStartDateRequired.trim().equalsIgnoreCase("true")){
						return Packages.java.lang.Boolean.TRUE;
					} else if (ownerStartDateRequired.trim().equalsIgnoreCase("false")){
						return Packages.java.lang.Boolean.FALSE;
					} else {
						throw "ap.project.owner.starDate.required MUST BE true or false";
					}
				} else {
					return Packages.java.lang.Boolean.TRUE;
				}
			};
		};
		new Logic(wfItem, dtoPj, superLogic, errors, messageUtil, request, gaService, wfService, wfTaskService, searchBuilderTemplate, log);
		

ethicCommiteeDeleteInconsistentDataProject
Questa validazione controlla che se non sono previste attività di ricerca che prevedono sperimentazioni passibili di giudizio da parte del Comitato Etico
e controlla che se non E' stata presentata la richiesta di parere all'OPBA o al Comitato Etico di Ateneo di riferimento o al Comitato Etico di un Ente Terzo che ha facoltà di concedere questo tipo di autorizzazioni.
I dati particolari di queste sottosezioni vengono svuotati se viene selezionato NO.
Dal punto di vista del modello dati si tratta degli elementi di tipo ethicCommiteeTopic
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

		//questa funzione elimina tutti i dati del tab, tranne ovviamente ethicCommiteeApplicability
		//viene chiamata quando non è applicabile
		function deleteAll(){
			
			//dati riguardanti il topic
			var wfItemElementSet = object.getWfItemElementSet();
			var ethicCommiteeTopicSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "ethicCommiteeTopic", wfService);
			
			var ethicCommiteeTopicSetIterator=ethicCommiteeTopicSet.iterator();
			while(ethicCommiteeTopicSetIterator.hasNext()){
				var wfItemElement=ethicCommiteeTopicSetIterator.next();
				
				var ethicCommiteeTopic= wfItemElement.getWfDictionaryMap().get("ethicCommiteeTopicId");
				var description= ethicCommiteeTopic.getDescription();
				//log.error("Topic description (ethicCommiteeTopicSet): "+description);
				
				wfService.deleteWfItemElement(wfItemElement.getId());
				//log.error("Eliminato con wfService");
				
				wfItemElementSet.remove(wfItemElement);
				//log.error("Eliminato dal set");
			}
			
			object.setWfItemElementSet(wfItemElementSet);
			//log.error("Sostituito set con nuovo");
			
			//dati riguardanti l'autorizzazione
			//log.error("ethicCommiteeSubmitted: "+object.getBooleanMap().get("ethicCommiteeSubmitted"));
			object.getBooleanMap().put("ethicCommiteeSubmitted", null);
			
			//log.error("ethicCommiteeSubmitDate: "+object.getDateMap().get("ethicCommiteeSubmitDate"));
			object.getDateMap().put("ethicCommiteeSubmitDate", null);
			
			//log.error("ethicCommiteeAuthorization: "+object.getWfDictionaryMap().get("ethicCommiteeAuthorization"));
			object.getWfDictionaryMap().put("ethicCommiteeAuthorization", null);
			
			deleteAuthorizationData();
		}
		
		//questa funzione elimina i dati riguardanti l'autorizzazione
		//viene chiamata quando non viene concessa
		function deleteAuthorizationData(){
			//log.error("ethicCommiteeAuthorizationNumber: "+object.getNumberMap().get("ethicCommiteeAuthorizationNumber"));
			object.getNumberMap().put("ethicCommiteeAuthorizationNumber", null);
			
			//log.error("ethicCommiteeAuthorizationDate: "+object.getDateMap().get("ethicCommiteeAuthorizationDate"));
			object.getDateMap().put("ethicCommiteeAuthorizationDate", null);
			
			//log.error("ethicCommiteeAuthorizationOrganization: "+object.getOrganizationUnitMap().get("ethicCommiteeAuthorizationOrganization"));
			var orgUnitMap=object.getOrganizationUnitMap().put("ethicCommiteeAuthorizationOrganization", null);
			
			wfService.saveOrUpdate(object);
			//log.error("SALVATO!");
		}
		
		//quando elimino da una mappa, non mi importa gestire se fosse popolata o meno
		//al massimo il remove mi restituisce null
		
		//log.error("Sono nel ethicCommiteeDeleteInconsistentData");
		
		//prima di tutto vado a vedere ethicCommiteeApplicability
		//SE NON E' SI (true), allora cancello tutti i dati sottostanti
		
		var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
		if (ethicCommiteeApplicability!=true){
			//chiamo la funzione per eliminare tutto
			deleteAll();
		}else{
			//non mi interessa ethicCommiteeSubmitted, deve essere per forza true se sono qui
			
			//SE E' SI, allora vado a vedere ethicCommiteeAuthorization
			var ethicCommiteeAuthorization= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
			
			//SE NON E' SPECIFICATO (null) O 'NON CONCESSO', allora cancello i dati relativi
			//TRANNE la data di presentazione
			//ci può essere il caso che sia stata fatta la richiesta e si stia aspettando il responso
			
			//non specificato, caso per evitare eccezioni
			if(ethicCommiteeAuthorization==null){
				deleteAuthorizationData();
			}else{
				var ethicCommiteeAuthorizationDescription= wfService.getWfDictionary(ethicCommiteeAuthorization.getId()).getDescription();
				if (!Packages.org.apache.commons.lang.StringUtils.equals("Concessa", ethicCommiteeAuthorizationDescription)){
					deleteAuthorizationData();
				}
			}
		}	
		

ownerValidatorProject
Questa validazione controlla che esista almeno un responsabile scientifico nel tab "Soggetti interni".
Dal punto di vista del modello dati si tratta degli elementi di tipo owner
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

		
			if (object.getId()==null){
				if (object.getPersonMap().get("owner")==null)
					errors.rejectValue("personMap[owner]","error.project.owner.required");
			} else {
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				if (
				!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))
				&&
				ownerSet.size()<1 
				&& 
				object.getPersonMap().get("owner")==null
				)
					errors.reject("error.project.owner.atLeast1");
			}
		

onlyOneOwnerValidatorProject
Questa validazione controlla che esista un solo responsabile scientifico nel tab "Soggetti interni".
Dal punto di vista del modello dati si tratta degli elementi di tipo owner
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

		
			if(!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				if(ownerSet.size() > 1){
					errors.reject("error.project.owner.max1");
				}
			}
		

ownerValidatorWithStartEndDateProject
Questa validazione opera sugli elementi owner (responsabile scientifico) figli dell'oggetto radice.
Viene verificato che esista almeno un responsabile scientifico e, se specificato un intervallo di validità per il singolo owner, viene verificato che sia compreso all'interno della validità dell'oggetto padre.
Gli attributi per le date di inizio e fine sono startDate e endDate sia per l'elemento owner che per l'oggetto padre.

			if (object.getId()==null){
				if (object.getPersonMap().get("owner")==null)
					errors.rejectValue("personMap[owner]","error.project.owner.required");
			} else {
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){
					if (ownerSet.size()<1 && object.getPersonMap().get("owner")==null)
						errors.reject("error.project.owner.atLeast1");
						
					var ownerSetIterator=ownerSet.iterator();
					
					var wfItemStartDate=object.getDateMap().get("startDate");
					var wfItemEndDate=object.getDateMap().get("endDate");
					var formatter =  Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");
					var ownerWithWrongInterval=[];
								
					while (ownerSetIterator.hasNext()){										
						var owner=ownerSetIterator.next();
						var wfItemElementStartDate=owner.getDateMap().get("startDate");
						
						if( wfItemElementStartDate!= null && wfItemStartDate && (wfItemElementStartDate.before(wfItemStartDate) || (wfItemEndDate!=null && wfItemElementStartDate.after(wfItemEndDate)))  ){
							ownerWithWrongInterval.push(owner.getPersonMap().get("ownerId").getDisplayValue());
						}								
					}
					
					if (ownerWithWrongInterval.length>0){
						errors.reject("error.project.owner.wrongInterval", [ownerWithWrongInterval.toString()], "error.project.owner.wrongInterval");
					}
				}
			}
		

organizationUnitValidatorProject
Questa validazione controlla che esista almeno una unità organizzativa interna nel tab "Soggetti interni".
Dal punto di vista del modello dati si tratta degli elementi di tipo internalOrganizationUnit
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
				if (orgUnitSet.size()<1)
					errors.reject("error.project.multipleInternalOrganization.atLeast1");		
			}
		

ethicCommiteeApplicabilityValidatorProject

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
				if(ethicCommiteeApplicability == null){
					errors.reject("error.project.ethicCommiteeApplicability.required");
				}
			}
		

ethicCommiteeTopicValidatorProject
Questa validazione controlla che esista almeno un Comitato Etico nel tab "Comitato Etico".
Dal punto di vista del modello dati si tratta degli elementi di tipo ethicCommiteeTopic
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			
			//log.error("Sono nel ethicCommiteeTopicValidatorProject");
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
				if (ethicCommiteeApplicability==true){
					//log.error("ethicCommiteeApplicability è true")
					//var ethicCommiteeTopicSet= object.getWfItemElementSet("ethicCommiteeTopic");
					var ethicCommiteeTopicSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "ethicCommiteeTopic", wfService);
					if(ethicCommiteeTopicSet.isEmpty()){
						//log.error("Nessun topic!");
						errors.reject("error.project.ethicCommiteeTopic.atLeast1");
					}	
				}
			}
		

ethicCommiteeSubmittedValidatorProject
Questa validazione controlla che deve essere stata presentata la richiesta di parere all'OPBA o al Comitato Etico di Ateneo di riferimento o al Comitato Etico di un Ente Terzo che ha facoltà di concedere questo tipo di autorizzazioni nel tab "Comitato Etico".
Dal punto di vista del modello dati si tratta degli elementi di tipo ethicCommiteeTopic
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

	
			//log.error("Sono nel ethicCommiteeSubmittedValidatorProject");		
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
				if (ethicCommiteeApplicability==true){
					//log.error("ethicCommiteeApplicability è true")
					var ethicCommiteeSubmitted= object.getBooleanMap().get("ethicCommiteeSubmitted");
					if(ethicCommiteeSubmitted!=true){
						//log.error("ethicCommiteeSubmitted è falso!");
						errors.reject("error.project.ethicCommiteeSubmitted.required");
					}	
				}
			}
		

ethicCommiteeAuthorizationNumberValidatorProject
Questa validazione controlla che se l'autorizzazione del Comitato Etico è stata concessa, deve essere presente il relativo numero identificativo nel tab "Comitato Etico".
Dal punto di vista del modello dati si tratta degli elementi di tipo ethicCommiteeTopic
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

	
			//log.error("Sono nel ethicCommiteeAuthorizationNumberValidatorProject");
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
				//prima di tutto si deve attivare solo se ethicCommiteeApplicability è su true
				if (ethicCommiteeApplicability==true){
					
					var ethicCommiteeSubmitted = object.getBooleanMap().get("ethicCommiteeSubmitted");
					//poi solo se ethicCommiteeSubmitted è su true
					if(ethicCommiteeSubmitted==true){
					
						var ethicCommiteeAuthorizationDictionary= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
						
						if(ethicCommiteeAuthorizationDictionary!=null){
						
							var ethicCommiteeAuthorizationDictionaryDescription= wfService.getWfDictionary(ethicCommiteeAuthorizationDictionary.getId()).getDescription();
							
							if (ethicCommiteeAuthorizationDictionaryDescription.equals("Concessa")){
								//se concessa allora il validator si deve attivare
								var ethicCommiteeAuthorizationNumber = object.getNumberMap().get("ethicCommiteeAuthorizationNumber");
								if(ethicCommiteeAuthorizationNumber==null){
									errors.reject("error.project.ethicCommiteeAuthorizationNumber.requiredIfGranted");
								}
							}
						}
					}
				}
			}
		

ethicCommiteeAuthorizationDateValidatorProject
Questa validazione controlla che se l'autorizzazione del Comitato Etico è stata concessa, deve essere presente la relativa data di concessione nel tab "Comitato Etico".
Dal punto di vista del modello dati si tratta degli elementi di tipo ethicCommiteeTopic
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

	
			//log.error("Sono nel ethicCommiteeAuthorizationDateValidatorProject");
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
				//prima di tutto si deve attivare solo se ethicCommiteeApplicability è su true
				if (ethicCommiteeApplicability==true){
					
					var ethicCommiteeSubmitted = object.getBooleanMap().get("ethicCommiteeSubmitted");
					//poi solo se ethicCommiteeSubmitted è su true
					if(ethicCommiteeSubmitted==true){
					
						var ethicCommiteeAuthorizationDictionary= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
						
						if(ethicCommiteeAuthorizationDictionary!=null){
						
							var ethicCommiteeAuthorizationDictionaryDescription= wfService.getWfDictionary(ethicCommiteeAuthorizationDictionary.getId()).getDescription();
							
							if (ethicCommiteeAuthorizationDictionaryDescription.equals("Concessa")){
								//se concessa allora il validator si deve attivare
								var ethicCommiteeAuthorizationDate = object.getDateMap().get("ethicCommiteeAuthorizationDate");
								if(ethicCommiteeAuthorizationDate==null){
									errors.reject("error.project.ethicCommiteeAuthorizationDate.requiredIfGranted");
								}
							}
						}
					}
				}
			}
		

ethicCommiteeAuthorizationOrganizationValidatorProject
Questa validazione controlla che Se l'autorizzazione è stata concessa, deve essere presente l'ente che l'ha concessa nel tab "Comitato Etico".
Dal punto di vista del modello dati si tratta degli elementi di tipo ethicCommiteeTopic
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

	
			//log.error("Sono nel ethicCommiteeAuthorizationOrganizationValidatorProject");
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
				//prima di tutto si deve attivare solo se ethicCommiteeApplicability è su true
				if (ethicCommiteeApplicability==true){
					
					var ethicCommiteeSubmitted = object.getBooleanMap().get("ethicCommiteeSubmitted");
					//poi solo se ethicCommiteeSubmitted è su true
					if(ethicCommiteeSubmitted==true){
					
						var ethicCommiteeAuthorizationDictionary= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
						
						if(ethicCommiteeAuthorizationDictionary!=null){
						
							var ethicCommiteeAuthorizationDictionaryDescription= wfService.getWfDictionary(ethicCommiteeAuthorizationDictionary.getId()).getDescription();
							
							if (ethicCommiteeAuthorizationDictionaryDescription.equals("Concessa")){
								//se concessa allora il validator si deve attivare
								var ethicCommiteeAuthorizationOrganization = object.getOrganizationUnitMap().get("ethicCommiteeAuthorizationOrganization");
								if(ethicCommiteeAuthorizationOrganization==null){
									errors.reject("error.project.ethicCommiteeAuthorizationOrganization.requiredIfGranted");
								}
							}
						}
					}
				}
			}
		

organizationUnitRoleValidatorProject
Questa validazione controlla che esista almeno una unità organizzativa interna, se esiste un ruolo principale deve essere definito.
Ci deve essere uno e un solo ruolo Principale (Main)
Dal punto di vista del modello dati si tratta degli elementi di tipo internalOrganizationUnit
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
				if (orgUnitSet.size()<1){
					errors.reject("error.project.multipleInternalOrganization.atLeast1");
				} else {
					var internalOrganizationUnitCoordinatorRole=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.internalOrganizationUnit.role.main");
					if (!internalOrganizationUnitCoordinatorRole){
						throw "Configuration variable ap.project.internalOrganizationUnit.role.main MUST BE DEFINED"; 								
					} else {
						internalOrganizationUnitCoordinatorRole=new Packages.java.lang.Integer(internalOrganizationUnitCoordinatorRole);
					}
					var orgUnitSetIterator=orgUnitSet.iterator();
					var count=0;											
					while (orgUnitSetIterator.hasNext()){											
						var element=orgUnitSetIterator.next();												
						var ouRole=element.getWfDictionaryMap().get("ouRole");
						if (ouRole!=null && internalOrganizationUnitCoordinatorRole.equals(ouRole.getId())){
							count++;	
						}												
					}
					if (count==0){
						errors.reject("error.project.multipleInternalOrganization.missingMain");
					}
					else if (count>1) {
						errors.reject("error.project.multipleInternalOrganization.tooManyMain");
					}
			} 		
		}
		

ownerAndOrganizationUnitMatchValidatorProject
Questa validazione controlla che esista per ogni responsabile scientifico del progetto, una unità organizzativa che sia interna nel momento della data di avvio del progetto (startDate) oppure se non c'è questa data in questo momento.
dal punto di vista del modello sono dei dati di tipo: internalOrganizationUnit, owner
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);				
				var ownerDepartmentSet=new Packages.java.util.HashSet();				
				var internalOrganizationUnitSet=new Packages.java.util.HashSet();
				
				var startDateFromWfItem=wfItem.getDateMap().get("startDate");
				if (startDateFromWfItem!=null){
					startDateFromWfItem=startDateFromWfItem.getTime();	
					if (ownerSet.size()>0){
						var ownerSetIterator=ownerSet.iterator();			
						while (ownerSetIterator.hasNext()){
							var ownerElement=ownerSetIterator.next();			
							var person=ownerElement.getPersonMap().get("ownerId");
							
							var ownerDepartmentPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
							ownerDepartmentPositionSearch.setPersonId(person.getId());
							ownerDepartmentPositionSearch.setDate(startDateFromWfItem);
							ownerDepartmentPositionSearch.setOrganizationUnitTypeDescription("department");
							ownerDepartmentPositionSearch.setDiscriminator("research");							
							var ownerDepartmentPositionSet = gaService.getPositionSearchList(ownerDepartmentPositionSearch, 0);
							var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(ownerDepartmentPositionSet, "research", "department");
							
							var ownerDepartmentPositionSetIterator=ownerDepartmentPositionSet.iterator();							
							while (ownerDepartmentPositionSetIterator.hasNext()){
								var position=ownerDepartmentPositionSetIterator.next();
								if (maxPriority == null || maxPriority.equals(position.getPriority())) {
									ownerDepartmentSet.add(position.getOrganizationUnit());														
									break;
								}
							}
						}
					}
					if (ownerDepartmentSet.size()>0){
						if (orgUnitSet.size()>0){
				 			var orgUnitSetIterator=orgUnitSet.iterator();			
							while (orgUnitSetIterator.hasNext()){											
								var wfItemElement=orgUnitSetIterator.next();												
								var orgUnit=wfItemElement.getOrganizationUnitMap().get("ouId");
								internalOrganizationUnitSet.add(orgUnit);
							}
						}
					}
					
					if(!internalOrganizationUnitSet.containsAll(ownerDepartmentSet)){
						var nonMatchedDepartmentCollection=Packages.org.apache.commons.collections.CollectionUtils.subtract(ownerDepartmentSet, internalOrganizationUnitSet);
						var nonMatchedDepartmentCollectionIterator=nonMatchedDepartmentCollection.iterator();
						var nonMatchedDepartmentString="";
						var counter=0;
						while(nonMatchedDepartmentCollectionIterator.hasNext()){
							var nonMatchedDepartment=nonMatchedDepartmentCollectionIterator.next();
							if (counter++>0)
								nonMatchedDepartmentString+=", ";
							nonMatchedDepartmentString+=nonMatchedDepartment.getDescription();
						}
						var df =  Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");
						var dateAsString=df.format(startDateFromWfItem);
						errors.reject("error.project.multipleInternalOrganization.matchWithDepartmentOwnerNotFound", [dateAsString, nonMatchedDepartmentString], null);
					}
				}
			}
		

contributorRoleValidatorProject
Questa validazione controlla che il ruolo del partecipante venga inserito (se è visibile nel form)
Dal punto di vista del modello dati si tratta dell' attributo roleId
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			if (Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.prj.contributor.role.enabled").equalsIgnoreCase("true")){							
				if(object.getWfDictionaryMap().get("roleId") == null ){
					errors.reject("error.project.contributor.role.required");					
				}
			}			
		

ownerRoleValidatorProject
Questa validazione controlla che il ruolo del responsabile venga inserito (se è visibile nel form)
Dal punto di vista del modello dati si tratta dell' attributo roleId
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			if (Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.prj.owner.role.enabled").equalsIgnoreCase("true")){							
				if(object.getWfDictionaryMap().get("roleId") == null ){
					errors.reject("error.project.owner.role.required");					
				}
			}			
		

grantorValidatorProject
Questa validazione controlla che esista almeno un ente finanziatore nel tab "Dati generali".
Dal punto di vista del modello dati si tratta degli elementi di tipo grantor
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){							
				var grantorSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "grantor", wfService);
				if (grantorSet.size()<1)
					errors.reject("error.project.grantor.atLeast1");
			}			
		

grantorApprovalDateValidatorProject

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var grantorApprovalDateFound=false;						
				var approvalSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "approval", wfService);
				var approvalSetIterator=approvalSet.iterator();
				while(approvalSetIterator.hasNext()){
					var approval=approvalSetIterator.next();
					var approvalType=approval.getWfDictionaryMap().get("approvalType");
					if (approvalType!=null && "approvalType.grantor".equals(approvalType.getInternalSourceIdentifier()) && approval.getDateMap().get("approvalDate")!=null){
						grantorApprovalDateFound=true;
						break;
					}					
				}
				if (!grantorApprovalDateFound){
					errors.reject("error.project.grantorApprovalDate.required");
				}			
			}			
		

topicValidatorProject
Questa validazione controlla che esista almeno una area tematica nel tab "Dati generali".
Dal punto di vista del modello dati si tratta degli elementi di tipo topic
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){							
				var topicSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "topic", wfService);
				if (topicSet.size()<1)
					errors.reject("error.project.topic.atLeast1");
			}			
		

evaluationValidatorProject
Questa validazione controlla che esista almeno un ente finanziatore nel tab "Dati generali".
Dal punto di vista del modello dati si tratta degli elementi di tipo grantor
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){							
				var evaluationSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "evaluation", wfService);
				if (evaluationSet.size()<1)
					errors.reject("error.project.evaluation.atLeast1");
			}			
		

administrativeOwnerValidatorProject
Questa validazione controlla che esista almeno un referente amministrativo nel tab "Soggetti interni".
Dal punto di vista del modello dati si tratta degli elementi di tipo administrativeOwner
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){						
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "administrativeOwner", wfService);
				if (ownerSet.size()<1)
					errors.reject("error.project.administrativeOwner.atLeast1");
			}
		

currencyAndInternalContributionValidatorProject
Questa validazione controlla che nel tab "Finanziamento", nel caso di selezione di valuta diversa da EURO, vengano specificati


Dal punto di vista del modello dati si tratta degli attributi: Per maggiori dettagli cfr. excel modello dati dell'entità Progetto
			
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){	
				var currency = object.getWfDictionaryMap().get("currency");	
				if(currency != null){			
					var currencyId = object.getWfDictionaryMap().get("currency").getId();
					var dictionary = wfService.getWfDictionary(currencyId);
					var currencyCode = dictionary.getStringMap().get("code");
					
					if (currencyCode != "currency.eur"){
						if (!object.getNumberMap().get("internalContributionOriginalCurrency")){       										
							errors.rejectValue("numberMap[internalContributionOriginalCurrency]","error.project.funding.internalContributionOriginalCurrency.required");									
						}
						if (!object.getNumberMap().get("exchangeRate")){
							errors.rejectValue("numberMap[exchangeRate]","error.project.funding.exchangeRate.required");									
						}
						if (!object.getDateMap().get("exchangeRateDate")){
							errors.rejectValue("dateMap[exchangeRateDate]","error.project.funding.exchangeRateDate.required");									
						}
					}
				}
			}
		

partnerAndGlobalCostValidatorProject
Questa validazione controlla la coerenza delle informazioni inserite nel tab "Partner".
Precisamente viene verificato che:

Inoltre nel caso in cui l'Ateneo risulti Coordinatore viene imposto che siano compilati i seguenti attributi nel fieldset "Dati finanziamento assegnato" del tab "Finanziamento": Per maggiori dettagli cfr. excel modello dati dell'entità Progetto.
Questa validazione si aspetta che siano definite le seguenti variabili di configurazione:
			
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var coordinatorRoleId=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.role.main");
				var uniquePartnerRoleId=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.role.uniquePartner");
				
				var myOrganization=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.myOrganization");
				if (coordinatorRoleId==null || myOrganization==null || uniquePartnerRoleId==null){
					throw "Configuration variables ap.project.partner.role.main, ap.project.partner.role.uniquePartner and ap.project.partner.myOrganization MUST BE DEFINED";
				} else {
					coordinatorRoleId=new Packages.java.lang.Integer(coordinatorRoleId);
					uniquePartnerRoleId=new Packages.java.lang.Integer(uniquePartnerRoleId);
					myOrganization=new Packages.java.lang.Integer(myOrganization);				
				}		
				var partnerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement", "partner",wfService);
				var partnerSetIterator=partnerSet.iterator();
				var counterOtherPartner=0;
				var counterCoordinator=0;
				var counterUniquePartner=0;
				var counterMyOrganization=0;
				while (partnerSetIterator.hasNext()){
					var element=partnerSetIterator.next();			 
					var orgUnitRole = element.getWfDictionaryMap().get("partnerRole");				
					if (orgUnitRole==null){
						errors.reject("error.project.partner.missingRole");
						break;					
					}					
					var orgUnit = element.getOrganizationUnitMap().get("partnerId");
					if (orgUnit==null){
						errors.reject("error.project.partner.missingOrgUnit");
						break;					
					}
					
					if (coordinatorRoleId.equals(orgUnitRole.getId())){
						counterCoordinator++;
					} else 	if (uniquePartnerRoleId.equals(orgUnitRole.getId())){
						counterUniquePartner++;
					} else {
						counterOtherPartner++;
					}
					
					if(myOrganization.equals(orgUnit.getId())){
						counterMyOrganization++;
					} 
					
					if(myOrganization.equals(orgUnit.getId()) && coordinatorRoleId.equals(orgUnitRole.getId())){
						
						if (!object.getNumberMap().get("globalContribution")){
							errors.rejectValue("numberMap[globalContribution]","error.project.funding.globalContribution.required");											
						}
						
						if (!object.getNumberMap().get("globalCost")){
							errors.rejectValue("numberMap[globalCost]","error.project.funding.globalCost.required");											
						}
						var currency = object.getWfDictionaryMap().get("currency");	
						if(currency != null){
							var currencyId = object.getWfDictionaryMap().get("currency").getId();
							var dictionary = wfService.getWfDictionary(currencyId);
							var currencyCode = dictionary.getStringMap().get("code");
							if (currencyCode != "currency.eur"){	
								if (!object.getNumberMap().get("globalCostOriginalCurrency")){
									errors.rejectValue("numberMap[globalCostOriginalCurrency]","error.project.funding.globalCostOriginalCurrency.required");											
								}										
								
								if (!object.getNumberMap().get("globalContributionOriginalCurrency")){
									errors.rejectValue("numberMap[globalContributionOriginalCurrency]","error.project.funding.globalContributionOriginalCurrency.required");											
								}
							}
						}
					}			
				}
				if (!errors.hasErrors()){
					if (counterCoordinator>1){									
					errors.reject("error.project.partner.tooManyMain");
					} else if (counterUniquePartner>1){									
						errors.reject("error.project.partner.tooManyUniquePartner");
					} else if (counterMyOrganization>1){
						errors.reject("error.project.partner.tooManyMyOrganization");
					} else if (partnerSet.size()>0){
						if (counterMyOrganization==0){
							errors.reject("error.project.partner.myOrganizationRequired");
						} else if (counterCoordinator>0 && counterUniquePartner>0){
							errors.reject("error.project.partner.coordinatorAndUniquePartner");
						} else if (counterOtherPartner>0 && counterCoordinator==0){
							errors.reject("error.project.partner.missingMain");
						} else if (counterOtherPartner>0 && counterUniquePartner>0){
							errors.reject("error.project.partner.otherPartnerAndUniquePartner");
						} else if (counterOtherPartner==0 && counterCoordinator>0){
							errors.reject("error.project.partner.coordinatorAndNoOtherPartner");
						}
					} else if(partnerSet.size() == 0){
						errors.reject("error.project.partner.required");
					}
				}	
			}		
		

checkInconsistentFundingValidatorProject
Questa validazione controlla la coerenza delle informazioni di finanziamento assegnato sia per le internalOganizationUnit (unità organizzative interne) che per i partner (Partner)
Viene controllato che le somme dei costi, contributi e cofinanziamenti per internalOrganizationUnit e partner coincidano con i totali specificati a livello di progetto.
Questa validazione viene attivata SOLO se ap.project.financing.consistence.validation.enabled=true
Viene fatta anche la validazione del finanziamento richiesto se e solo se ap.project.finacing.requested.enabled=true
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto.

	
			if (Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.financing.consistence.validation.enabled").equalsIgnoreCase("true")){
				if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
					var checkRequested = false;
					if (!Packages.java.lang.Boolean.TRUE.equals(Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.finacing.requested.enabled"))){
						checkRequested = true;
					}
					var iouSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement", "internalOrganizationUnitCost", wfService);
					var iouSetIterator=iouSet.iterator();	 
					var cost = 0;	
					var contribution = 0;
					var cofinancing = 0;
					var cost2 = 0;	
					var contribution2 = 0;
					var cofinancing2 = 0;
					while (iouSetIterator.hasNext()){
						var element = iouSetIterator.next();	
						if(checkRequested){
							cost = +cost + +element.getNumberMap().get("ouRequestedCost");	
							contribution = +contribution + +element.getNumberMap().get("ouRequestedContribution");
							cofinancing = +cofinancing + +element.getNumberMap().get("ouRequestedCofinancing");
						}		 
						cost2 = +cost2 + +element.getNumberMap().get("ouCost");	
						contribution2 = +contribution2 + +element.getNumberMap().get("ouContribution");
						cofinancing2 = +cofinancing2 + +element.getNumberMap().get("ouCofinancing");
					}
					if(cost != 0){
						if(wfItem.getNumberMap().get("requestedInternalCost") != cost){
							errors.rejectValue("numberMap[requestedInternalCost]","error.project.internalOrganizationUnit.requested.cost.inconsistent");
						}
					}
					if(contribution != 0){
						if(wfItem.getNumberMap().get("requestedInternalContribution") != contribution){
							errors.rejectValue("numberMap[requestedInternalContribution]","error.project.internalOrganizationUnit.requested.contribution.inconsistent");
						}
					}
					if(cofinancing != 0){
						if(wfItem.getNumberMap().get("requestedInternalCofinancing") != cofinancing){
							errors.rejectValue("numberMap[requestedInternalCofinancing]","error.project.internalOrganizationUnit.requested.cofinancing.inconsistent");
						}
					}
								
					if(cost2 != 0){
						if(wfItem.getNumberMap().get("internalCost") != cost2){
							errors.rejectValue("numberMap[internalCost]","error.project.internalOrganizationUnit.cost.inconsistent");
						}
					}
					if(contribution2 != 0){
						if(wfItem.getNumberMap().get("internalContribution") != contribution2){
							errors.rejectValue("numberMap[internalContribution]","error.project.internalOrganizationUnit.contribution.inconsistent");
						}
					}
					if(cofinancing2 != 0){
						if(wfItem.getNumberMap().get("internalCofinancing") != cofinancing2){
							errors.rejectValue("numberMap[internalCofinancing]","error.project.internalOrganizationUnit.cofinancing.inconsistent");
						}
					}
								
					var partnerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement", "partnerCost", wfService);
					var partnerSetIterator=partnerSet.iterator();	 
					cost = 0;	
					contribution = 0;
					var cost2 = 0;	
					var contribution2 = 0;
					while (partnerSetIterator.hasNext()){
						var element = partnerSetIterator.next();	
						if(checkRequested){		 
							cost = +cost + +element.getNumberMap().get("partnerRequestedCost");	
							contribution = +contribution + +element.getNumberMap().get("partnerRequestedContribution");
						}
						cost2 = +cost2 + +element.getNumberMap().get("partnerCost");	
						contribution2 = +contribution2 + +element.getNumberMap().get("partnerContribution");
					}
					if(cost != 0){
						if(wfItem.getNumberMap().get("requestedGlobalCost") != cost){
							errors.rejectValue("numberMap[requestedGlobalCost]","error.project.partner.requested.cost.inconsistent");
						}
					}
					if(contribution != 0){
						if(wfItem.getNumberMap().get("requestedGlobalContribution") != contribution){
							errors.rejectValue("numberMap[requestedGlobalContribution]","error.project.partner.requested.contribution.inconsistent");
						}
					}
									
				
					if(cost2 != 0){
						if(wfItem.getNumberMap().get("globalCost") != cost2){
							errors.rejectValue("numberMap[globalCost]","error.project.partner.cost.inconsistent");
						}
					}
					if(contribution2 != 0){
						if(wfItem.getNumberMap().get("globalContribution") != contribution2){
							errors.rejectValue("numberMap[globalContribution]","error.project.partner.contribution.inconsistent");
						}
					}
				}
			}
			
		

uniqueIdentifierProject
Questa validazione controlla l'unicità dell'identificativo dell'oggetto.
Questa verifica viene fatta per i casi di generazione di codice "parlante" con possibile collisione con identificativi già presenti.

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){				
				var paramMap = new Packages.java.util.HashMap();
				paramMap.put("identifier", object.getIdentifier());			
				
				var count=searchBuilderTemplate.getSingleObject("getWfItemCount", paramMap);
				if (count>1)
					errors.reject("error.project.identifier.notUnique");			
			}
		

internalOrganizationUnitEditValidator
Questa validazione impedisce la modifica della Struttura in internalOganizationUnit
se tale Struttura è presente in internalOganizationUnitCost (finanziamenti associati a unità organizzative interne).
Agisce in caso di modifica dei valori del fragment.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getWfItem().getBooleanMap().get("legacy"))){		
				var iouSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);				
				var iouCostSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnitCost", wfService);				
				var iouSetIterator=iouSet.iterator();
				var iouCostSetIterator=iouCostSet.iterator();
				var ouSet = new Packages.java.util.HashSet();
				while (iouSetIterator.hasNext()){
					var element = iouSetIterator.next();
					ouSet.add(element.getOrganizationUnitMap().get("ouId"));
				}
				var ouCostSet = new Packages.java.util.HashSet();
				while (iouCostSetIterator.hasNext()){
					var element = iouCostSetIterator.next();
					ouCostSet.add(element.getOrganizationUnitMap().get("ouId"));
				}
				if(!ouSet.containsAll(ouCostSet)){
					errors.reject("error.project.internalOrganizationUnit.editOrDelete");
				}
			}
		

internalOrganizationUnitDeleteValidator
Questa validazione impedisce l'eliminazione di un elemento in internalOganizationUnit
se la Struttura associata è presente in internalOganizationUnitCost (finanziamenti associati a unità organizzative interne).
Agisce in caso di eliminazione dei valori del fragment

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getWfItem().getBooleanMap().get("legacy"))){		
				var iouCostSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnitCost", wfService);				
				var iouCostSetIterator=iouCostSet.iterator();
				var ouCostSet = new Packages.java.util.HashSet();
				while (iouCostSetIterator.hasNext()){
					var element = iouCostSetIterator.next();
					ouCostSet.add(element.getOrganizationUnitMap().get("ouId"));
				}
				if(ouCostSet.contains(object.getOrganizationUnitMap().get("ouId"))){
					errors.reject("error.project.internalOrganizationUnit.editOrDelete");
				}
			}
		

internalOrganizationUnitCostEditValidator
Questa validazione impedisce la modifica della Struttura in internalOganizationUnitCost (finanziamenti associati a unità organizzative interne)
se tale Struttura è presente in internalOganizationUnit.
Agisce in caso di modifica dei valori del fragment

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getWfItem().getBooleanMap().get("legacy"))){		
				var iouSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);				
				var iouSetIterator=iouSet.iterator();
				var ouSet = new Packages.java.util.HashSet();
				while (iouSetIterator.hasNext()){
					var element = iouSetIterator.next();
					ouSet.add(element.getOrganizationUnitMap().get("ouId"));
				}
				if(!ouSet.contains(object.getOrganizationUnitMap().get("ouId"))){
					errors.reject("error.project.internalOrganizationUnitCost.editOrAdd");
				}
			}
		

partnerEditValidator
Questa validazione impedisce la modifica del Partner in partner
se tale Partner è presente in partnerCost (finanziamenti associati a partner).
Agisce in caso di modifica dei valori del fragment.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getWfItem().getBooleanMap().get("legacy"))){		
				var partnerSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "partner", wfService);				
				var partnerCostSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "partnerCost", wfService);				
				var partnerSetIterator = partnerSet.iterator();
				var partnerCostSetIterator = partnerCostSet.iterator();
				var partnerSet = new Packages.java.util.HashSet();
				while (partnerSetIterator.hasNext()){
					var element = partnerSetIterator.next();
					partnerSet.add(element.getOrganizationUnitMap().get("partnerId"));
				}
				var partnerCostSet = new Packages.java.util.HashSet();
				while (partnerCostSetIterator.hasNext()){
					var element = partnerCostSetIterator.next();
					partnerCostSet.add(element.getOrganizationUnitMap().get("partnerId"));
				}
				if(!partnerSet.containsAll(partnerCostSet)){
					errors.reject("error.project.partner.editOrDelete");
				}
			}
		

partnerDeleteValidator
Questa validazione impedisce l'eliminazione di un elemento in partner
se il Partner associata è presente in partnerCost (finanziamenti associati a partner).
Agisce in caso di eliminazione dei valori del fragment.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getWfItem().getBooleanMap().get("legacy"))){		
				var partnerCostSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "partnerCost", wfService);				
				var partnerCostSetIterator= partnerCostSet.iterator();
				
				var partnerCostSet = new Packages.java.util.HashSet();
				while (partnerCostSetIterator.hasNext()){
					var element = partnerCostSetIterator.next();
					partnerCostSet.add(element.getOrganizationUnitMap().get("partnerId"));
				}
				if(partnerCostSet.contains(object.getOrganizationUnitMap().get("partnerId"))){
					errors.reject("error.project.partner.editOrDelete");
				}
			}
		

partnerCostEditValidator
Questa validazione impedisce la modifica del Partner in partnerCost (finanziamenti associati a partner)
se tale Partner è presente in partner.
Agisce in caso di modifica dei valori del fragment.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getWfItem().getBooleanMap().get("legacy"))){		
				var partnerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object.getWfItem(), "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "partner", wfService);				
				var partnerSetIterator = partnerSet.iterator();
				var partnerSet = new Packages.java.util.HashSet();
				while (partnerSetIterator.hasNext()){
					var element = partnerSetIterator.next();
					partnerSet.add(element.getOrganizationUnitMap().get("partnerId"));
				}
				if(!partnerSet.contains(object.getOrganizationUnitMap().get("partnerId"))){
					errors.reject("error.project.partnerCost.editOrAdd");
				}
			}
		

notEditableByOwnerValidator

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getBooleanMap().get("legacy"))){		
				var reject = 0;
				var discriminator = [null, null, "acronym"];
				var column = ["wfItemTypeId", "description","string"];
				columnLen = column.length;
				var value = [];
				for (i = 0; i < columnLen; i++) {
					var discriminatorString = discriminator[i] == null ? '' : "." + discriminator[i];
					if(Packages.java.lang.Boolean.TRUE.equals(Packages.it.cilea.wf.util.WfUtil.isAttributeChanged(wfService, wfItem, column[i] + discriminatorString))){
						reject = 1;
						break;
					}
				}
				if(reject > 0){
					errors.reject("error.project.ownerGeneralData.edit.notAllowed");
				}
			}
		

itemTypeAndTeamEditableValidator
Questa validazione controlla che l'utente corrente NON appartenga al team "Ufficio Erasmus - Progetti con caricamento delle persone abilitate".
Questo è un team con agganciata la funzione "Risorsa per Ufficio Erasmus cui negare accesso in modifica ai Progetti" (/ap/project/erasmusTeam/onlyRead.function)

La visione completa consente a chiunque appartenga al team di accedere con i diritti di helpdesk SOLO al flusso per i Progetti di Formazione.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				var gaUserDetail = Packages.it.cilea.ga.authorization.context.GaAuthorizationUserHolder.getUser();	
				var userId = gaUserDetail.getUserId();
				
				var searchCommand = new Packages.it.cilea.ga.command.TeamUserLinkSearchCommand();
				searchCommand.setUserId(userId);
				var linkList = gaService.getTeamUserLinkSearchList(searchCommand, 0);
				var listIterator = linkList.iterator();			
				var foundTeam = 0;	
				while(listIterator.hasNext()){
					var teamUserLink = listIterator.next();		
					if(teamUserLink.getTeamId() == Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.onlyRead.erasmusTeam")){
						foundTeam = 1;
						if(!Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.onlyRead.erasmusItemType").contains(object.getWfItemType().getIdentifier())){
							errors.reject("error.project.erasmus.operation.itemType.notAllowed");
						} 
						break;
					} 
				} 
				if(foundTeam == 0){
					if(Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.onlyRead.erasmusItemType").contains(object.getWfItemType().getIdentifier())){
						errors.reject("error.project.erasmus.operation.team.notAllowed");
					}
				}
			}
		

itemTypeAndTeamCreatableValidator
Questa validazione controlla che l'utente corrente NON appartenga al team "Ufficio Erasmus - Progetti con caricamento delle persone abilitate".
Questo è un team con agganciata la funzione "Risorsa per Ufficio Erasmus cui negare accesso in modifica ai Progetti" (/ap/project/erasmusTeam/onlyRead.function)

La visione completa consente a chiunque appartenga al team di creare una scheda SOLO per il flusso per i Progetti di Formazione.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				var gaUserDetail = Packages.it.cilea.ga.authorization.context.GaAuthorizationUserHolder.getUser();	
				var authority = gaUserDetail.getCurrentAuthorityIdentifier();
				if(authority == "ROLE_ADMIN"){
					var validateLogic = Packages.it.cilea.wf.WfConstant.VALIDATE_LOGIC_MAP.get("itemTypeAndTeamEditableValidator");
					validateLogic.validate(request, object, errors);
				}
			}
		

projectCallValidator
Questa validazione controlla che esista uno ed un solo bando di finanziamento associato a questo progetto nel tab "Dati generali".
Viene verificato inoltre che il bando di finanziamento sia in stato approvato
Dal punto di vista del modello dati si tratta degli elementi di tipo callProjectLink
Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){
				var linkSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getParentWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "callProjectLink", wfService);
				//log.error("linkSet: " + linkSet);			
				if (linkSet.size()>1){
					errors.reject("error.project.call.moreThanOne");
				} else if (linkSet.size()==1){
					var linkSetIterator = linkSet.iterator();
					if( linkSetIterator.hasNext() ){
						var linkElement = linkSetIterator.next();
						var call = linkElement.getParent();
		                var callState = call.getWfState().getDescription();	 
						if (
						 	!Packages.org.apache.commons.lang.StringUtils.equals("approved", callState)
						 	){
						 		errors.reject("error.project.call.notApproved");
						 	}
					}
				}
			}
		

wfStartLogicProposal

			var person=wfItem.getPersonMap().get("owner");
			person=gaService.getPerson(person.getId());
			
			var ownerElement=new Packages.it.cilea.wf.model.WfItemElement();
			ownerElement.setDiscriminator("owner");
			ownerElement.setWfItemId(wfItem.getId());
			ownerElement.getPersonMap().put("ownerId", person);			
			wfService.saveOrUpdate(ownerElement);
			wfItem.getPersonMap().put("owner", null);
			
			
			var positionLastSet = person.getPositionLastSet();											
			var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionLastSet, "research", "department");
			positionLastSetIterator=positionLastSet.iterator();											
			while (positionLastSetIterator.hasNext()){
				var position=positionLastSetIterator.next();
				if (maxPriority == null || maxPriority.equals(position.getPriority())) {
					if ("research".equals(position.getDiscriminator()) && "department"
								.equals(position.getOrganizationUnit().getOrganizationUnitType().getDescription())) {
						var internalOrganizationUnitElement=new Packages.it.cilea.wf.model.WfItemElement();
						internalOrganizationUnitElement.setDiscriminator("internalOrganizationUnit");
						internalOrganizationUnitElement.setWfItemId(wfItem.getId());
						var internalOrganizationUnitRoleId = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.internalOrganizationUnit.role.main");
						if (internalOrganizationUnitRoleId==null) 
							throw "ERROR on wfStartLogicProposal: internalOrganizationUnitRoleId is NULL ";
						var internalOrganizationUnitRole = wfService.getWfDictionary(new Packages.java.lang.Integer(internalOrganizationUnitRoleId));
						if (internalOrganizationUnitRole==null) 
							throw "ERROR on wfStartLogicProposal: internalOrganizationUnitRole is NULL ";
						internalOrganizationUnitElement.getOrganizationUnitMap().put("ouId", position.getOrganizationUnit());
						internalOrganizationUnitElement.getWfDictionaryMap().put("ouRole", internalOrganizationUnitRole);						
						wfService.saveOrUpdate(internalOrganizationUnitElement);
						break;
					}
				}
			}		
			
			//partner
			var uniquePartnerRoleId=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.role.uniquePartner");
			var myOrganization=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.myOrganization");
			if (uniquePartnerRoleId==null || myOrganization==null){
				throw "Configuration variables ap.project.partner.role.uniquePartner and ap.project.partner.myOrganization MUST BE DEFINED";
			} else {				
				uniquePartnerRoleId=wfService.getWfDictionary(new Packages.java.lang.Integer(uniquePartnerRoleId));				
				myOrganization=gaService.getOrganizationUnit(new Packages.java.lang.Integer(myOrganization));
				
				var partnerElement=new Packages.it.cilea.wf.model.WfItemElement();
				partnerElement.setDiscriminator("partner");
				partnerElement.setWfItemId(wfItem.getId());
				partnerElement.getOrganizationUnitMap().put("partnerId", myOrganization);
				partnerElement.getWfDictionaryMap().put("partnerRole", uniquePartnerRoleId);
				wfService.saveOrUpdate(partnerElement);				
			}
			
			
			var lastName=person.getLastName().replaceAll("\s", "");
			lastName=lastName.replaceAll("'", "");
			lastName=(lastName.length()>=4)?lastName.substring(0,4):lastName.substring(0,lastName.length());
			lastName=lastName.toUpperCase();
			
			var firstName=person.getFirstName().substring(0,1);
			firstName=firstName.toUpperCase();	
			
			var startDate=wfItem.getDateMap().get("startDate");
			var year=startDate.get(Packages.java.util.Calendar.YEAR);
			
			var yearString=new Packages.java.lang.Integer(year).toString();
			yearString=yearString.substring(2);			
			
			var sourceItemTypeCode=wfItem.getWfItemType().getCode();
			var identifier="PRO_"+sourceItemTypeCode+yearString+firstName+lastName+"_";
			
			var paramMap = new Packages.java.util.HashMap();
			paramMap.put("identifier", identifier);
			paramMap.put("excludeIdentifier", identifier+"M");
			
			var count=searchBuilderTemplate.getSingleObject("getMaxItemCountForGivenIdentifier", paramMap);
			var countString="";
			if (count<9)
				countString+="0";			
			countString+=(count.intValue()+1);
			identifier+=countString;			
			wfItem.setIdentifier(identifier);
			wfItem.setYear(new Packages.java.lang.Integer(year));
			true;
			

wfActionLogicEnterProposalMailSender

			var mailEnableParam = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.proposal.mail.enable");
			var mailHtmlEnableParam = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.proposal.mail.html.enable");
			var isHtml;
			if(mailHtmlEnableParam.equalsIgnoreCase("true")){
				isHtml = true;
			}
			else{
				isHtml = false;
			}
			if (mailEnableParam!=null && mailEnableParam.equalsIgnoreCase("true")){
				var wfItemIdentifier = wfItem.getIdentifier();
				var wfItemDescription = wfItem.getDescription();
				var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
				var ownerSetIterator=ownerSet.iterator();
				while(ownerSetIterator.hasNext()){
					var ownerElement=ownerSetIterator.next();
					var person = ownerElement.getPersonMap().get("ownerId");
					person = gaService.getPerson(person.getId());
					var contact=person.getPrincipalContactMap().get("mail");
					var surnameName = person.getLastName()+" "+person.getFirstName();
					var subjectLabel=messageUtil.findMessage("label.ap.proposal.mail.subject", [wfItemIdentifier]);
					var textLabel=messageUtil.findMessage("label.ap.proposal.mail.text",[wfItemIdentifier, surnameName, wfItemDescription, wfItem.getWfState().getDisplayValue()]);
					mailService.send("no-reply@cineca.it", [contact], null, null, subjectLabel, textLabel, null, isHtml);
				}
			}
		

ethicCommiteeDeleteInconsistentDataProposal

		//questa funzione elimina tutti i dati del tab, tranne ovviamente ethicCommiteeApplicability
		//viene chiamata quando non è applicabile
		function deleteAll(){
			
			//dati riguardanti il topic
			var wfItemElementSet = object.getWfItemElementSet();
			var ethicCommiteeTopicSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "ethicCommiteeTopic", wfService);
			
			var ethicCommiteeTopicSetIterator=ethicCommiteeTopicSet.iterator();
			while(ethicCommiteeTopicSetIterator.hasNext()){
				var wfItemElement=ethicCommiteeTopicSetIterator.next();
				
				var ethicCommiteeTopic= wfItemElement.getWfDictionaryMap().get("ethicCommiteeTopicId");
				var description= ethicCommiteeTopic.getDescription();
				//log.error("Topic description (ethicCommiteeTopicSet): "+description);
				
				wfService.deleteWfItemElement(wfItemElement.getId());
				//log.error("Eliminato con wfService");
				
				wfItemElementSet.remove(wfItemElement);
				//log.error("Eliminato dal set");
			}
			
			object.setWfItemElementSet(wfItemElementSet);
			//log.error("Sostituito set con nuovo");
			
			//dati riguardanti l'autorizzazione
			//log.error("ethicCommiteeSubmitted: "+object.getBooleanMap().get("ethicCommiteeSubmitted"));
			object.getBooleanMap().put("ethicCommiteeSubmitted", null);
			
			//log.error("ethicCommiteeSubmitDate: "+object.getDateMap().get("ethicCommiteeSubmitDate"));
			object.getDateMap().put("ethicCommiteeSubmitDate", null);
			
			//log.error("ethicCommiteeAuthorization: "+object.getWfDictionaryMap().get("ethicCommiteeAuthorization"));
			object.getWfDictionaryMap().put("ethicCommiteeAuthorization", null);
			
			deleteAuthorizationData();
		}
		
		//questa funzione elimina i dati riguardanti l'autorizzazione
		//viene chiamata quando non viene concessa
		function deleteAuthorizationData(){
			//log.error("ethicCommiteeAuthorizationNumber: "+object.getNumberMap().get("ethicCommiteeAuthorizationNumber"));
			object.getNumberMap().put("ethicCommiteeAuthorizationNumber", null);
			
			//log.error("ethicCommiteeAuthorizationDate: "+object.getDateMap().get("ethicCommiteeAuthorizationDate"));
			object.getDateMap().put("ethicCommiteeAuthorizationDate", null);
			
			//log.error("ethicCommiteeAuthorizationOrganization: "+object.getOrganizationUnitMap().get("ethicCommiteeAuthorizationOrganization"));
			var orgUnitMap=object.getOrganizationUnitMap().put("ethicCommiteeAuthorizationOrganization", null);
			
			wfService.saveOrUpdate(object);
			//log.error("SALVATO!");
		}
		
		//quando elimino da una mappa, non mi importa gestire se fosse popolata o meno
		//al massimo il remove mi restituisce null
		
		//log.error("Sono nel ethicCommiteeDeleteInconsistentData");
		
		//prima di tutto vado a vedere ethicCommiteeApplicability
		//SE NON E' SI (true), allora cancello tutti i dati sottostanti
		
		var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
		if (ethicCommiteeApplicability!=true){
			//chiamo la funzione per eliminare tutto
			deleteAll();
		}else{
			//non mi interessa ethicCommiteeSubmitted, deve essere per forza true se sono qui
			
			//SE E' SI, allora vado a vedere ethicCommiteeAuthorization
			var ethicCommiteeAuthorization= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
			
			//SE NON E' SPECIFICATO (null) O 'NON CONCESSO', allora cancello i dati relativi
			//TRANNE la data di presentazione
			//ci può essere il caso che sia stata fatta la richiesta e si stia aspettando il responso
			
			//non specificato, caso per evitare eccezioni
			if(ethicCommiteeAuthorization==null){
				deleteAuthorizationData();
			}else{
				var ethicCommiteeAuthorizationDescription= wfService.getWfDictionary(ethicCommiteeAuthorization.getId()).getDescription();
				if (!Packages.org.apache.commons.lang.StringUtils.equals("Concessa", ethicCommiteeAuthorizationDescription)){
					deleteAuthorizationData();
				}
			}
		}	
		

ownerStartValidatorProposal

			if (object.getId()==null && object.getPersonMap().get("owner")==null){
				errors.rejectValue("personMap[owner]","error.proposal.owner.required");
			}
		

ownerValidatorProposal

			
			var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
			if (ownerSet.size()<1)
				errors.reject("error.proposal.owner.atLeast1");		
		

organizationUnitValidatorProposal

			
			var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
			if (orgUnitSet.size()<1)
				errors.reject("error.proposal.multipleInternalOrganization.atLeast1");		
		

ethicCommiteeTopicValidatorProposal

			
			//log.error("Sono nel ethicCommiteeTopicValidatorProposal");
			var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
			if (ethicCommiteeApplicability==true){
				//log.error("ethicCommiteeApplicability è true")
				//var ethicCommiteeTopicSet= object.getWfItemElementSet("ethicCommiteeTopic");
				var ethicCommiteeTopicSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "ethicCommiteeTopic", wfService);
				if(ethicCommiteeTopicSet.isEmpty()){
					//log.error("Nessun topic!");
					errors.reject("error.proposal.ethicCommiteeTopic.atLeast1");
				}	
			}
		

ethicCommiteeSubmittedValidatorProposal

	
			//log.error("Sono nel ethicCommiteeSubmittedValidatorProposal");		
			var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
			if (ethicCommiteeApplicability==true){
				//log.error("ethicCommiteeApplicability è true")
				var ethicCommiteeSubmitted= object.getBooleanMap().get("ethicCommiteeSubmitted");
				if(ethicCommiteeSubmitted!=true){
					//log.error("ethicCommiteeSubmitted è falso!");
					errors.reject("error.proposal.ethicCommiteeSubmitted.required");
				}	
			}
		

ethicCommiteeAuthorizationNumberValidatorProposal

	
			//log.error("Sono nel ethicCommiteeAuthorizationNumberValidatorProposal");
			var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
			//prima di tutto si deve attivare solo se ethicCommiteeApplicability è su true
			if (ethicCommiteeApplicability==true){
				
				var ethicCommiteeSubmitted = object.getBooleanMap().get("ethicCommiteeSubmitted");
				//poi solo se ethicCommiteeSubmitted è su true
				if(ethicCommiteeSubmitted==true){
				
					var ethicCommiteeAuthorizationDictionary= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
					
					if(ethicCommiteeAuthorizationDictionary!=null){
					
						var ethicCommiteeAuthorizationDictionaryDescription= wfService.getWfDictionary(ethicCommiteeAuthorizationDictionary.getId()).getDescription();
						
						if (ethicCommiteeAuthorizationDictionaryDescription.equals("Concessa")){
							//se concessa allora il validator si deve attivare
							var ethicCommiteeAuthorizationNumber = object.getNumberMap().get("ethicCommiteeAuthorizationNumber");
							if(ethicCommiteeAuthorizationNumber==null){
								errors.reject("error.proposal.ethicCommiteeAuthorizationNumber.requiredIfGranted");
							}
						}
					}
				}
			}
			
		

ethicCommiteeAuthorizationDateValidatorProposal

	
			//log.error("Sono nel ethicCommiteeAuthorizationDateValidatorProposal");
			var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
			//prima di tutto si deve attivare solo se ethicCommiteeApplicability è su true
			if (ethicCommiteeApplicability==true){
				
				var ethicCommiteeSubmitted = object.getBooleanMap().get("ethicCommiteeSubmitted");
				//poi solo se ethicCommiteeSubmitted è su true
				if(ethicCommiteeSubmitted==true){
				
					var ethicCommiteeAuthorizationDictionary= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
					
					if(ethicCommiteeAuthorizationDictionary!=null){
					
						var ethicCommiteeAuthorizationDictionaryDescription= wfService.getWfDictionary(ethicCommiteeAuthorizationDictionary.getId()).getDescription();
						
						if (ethicCommiteeAuthorizationDictionaryDescription.equals("Concessa")){
							//se concessa allora il validator si deve attivare
							var ethicCommiteeAuthorizationDate = object.getDateMap().get("ethicCommiteeAuthorizationDate");
							if(ethicCommiteeAuthorizationDate==null){
								errors.reject("error.proposal.ethicCommiteeAuthorizationDate.requiredIfGranted");
							}
						}
					}
				}
			}
			
		

ethicCommiteeAuthorizationOrganizationValidatorProposal

	
			//log.error("Sono nel ethicCommiteeAuthorizationOrganizationValidatorProposal");
			var ethicCommiteeApplicability = object.getBooleanMap().get("ethicCommiteeApplicability");
			//prima di tutto si deve attivare solo se ethicCommiteeApplicability è su true
			if (ethicCommiteeApplicability==true){
				
				var ethicCommiteeSubmitted = object.getBooleanMap().get("ethicCommiteeSubmitted");
				//poi solo se ethicCommiteeSubmitted è su true
				if(ethicCommiteeSubmitted==true){
				
					var ethicCommiteeAuthorizationDictionary= object.getWfDictionaryMap().get("ethicCommiteeAuthorization");
					
					if(ethicCommiteeAuthorizationDictionary!=null){
					
						var ethicCommiteeAuthorizationDictionaryDescription= wfService.getWfDictionary(ethicCommiteeAuthorizationDictionary.getId()).getDescription();
						
						if (ethicCommiteeAuthorizationDictionaryDescription.equals("Concessa")){
							//se concessa allora il validator si deve attivare
							var ethicCommiteeAuthorizationOrganization = object.getOrganizationUnitMap().get("ethicCommiteeAuthorizationOrganization");
							if(ethicCommiteeAuthorizationOrganization==null){
								errors.reject("error.proposal.ethicCommiteeAuthorizationOrganization.requiredIfGranted");
							}
						}
					}
				}
			}
			
		

uniqueParentProject

			var linkSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getChildWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "link", wfService);
			//log.error("linkSet: " + linkSet);			
			if (linkSet.size()>1){
				errors.reject("error.proposal.parentProject.moreThanOneParentProposal");
			} else if (linkSet.size()==1){
				var linkSetIterator = linkSet.iterator();
				if( linkSetIterator.hasNext() ){
					var linkElement = linkSetIterator.next();
					var project = linkElement.getParent();
	                var projectState = project.getWfState().getDescription();	 
					if (
					 	!Packages.org.apache.commons.lang.StringUtils.equals("approved", projectState) 
					 	&&
					 	!Packages.org.apache.commons.lang.StringUtils.equals("concluded", projectState)
					 	){
					 		errors.reject("error.proposal.parentProject.notApprovedOrConcluded");
					 	} else {					 		
					 		var paramMap = new Packages.java.util.HashMap();
							paramMap.put("parentId", project.getId());
							var count=searchBuilderTemplate.getSingleObject("getProposalChildProject", paramMap);
							if (count>0)
								errors.reject("error.proposal.parentProject.notUnique");
					 	}					 
				}
			} else if (linkSet.size()==0) {
				//ok don't do anythig, just chill out bro
			}
		

organizationUnitRoleValidatorProposal

			
			var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
			if (orgUnitSet.size()<1){
				errors.reject("error.proposal.multipleInternalOrganization.atLeast1");
			} else {
				var internalOrganizationUnitCoordinatorRole=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.internalOrganizationUnit.role.main");
				if (!internalOrganizationUnitCoordinatorRole){
					throw "Configuration variable ap.proposal.internalOrganizationUnit.role.main MUST BE DEFINED"; 								
				} else {
					internalOrganizationUnitCoordinatorRole=new Packages.java.lang.Integer(internalOrganizationUnitCoordinatorRole);
				}
				var orgUnitSetIterator=orgUnitSet.iterator();
				var count=0;											
				while (orgUnitSetIterator.hasNext()){											
					var element=orgUnitSetIterator.next();												
					var ouRole=element.getWfDictionaryMap().get("ouRole");
					if (ouRole!=null && internalOrganizationUnitCoordinatorRole.equals(ouRole.getId())){
						count++;	
					}												
				}
				if (count==0){
					errors.reject("error.proposal.multipleInternalOrganization.missingMain");
				}
				else if (count>1) {
					errors.reject("error.proposal.multipleInternalOrganization.tooManyMain");
				}
		} 		
		

ownerAndOrganizationUnitMatchValidatorProposal

			
			var orgUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
			var ownerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
			var ownerDepartmentSet=new Packages.java.util.HashSet();
			var internalOrganizationUnitSet=new Packages.java.util.HashSet();
			
			var startDateFromWfItem=wfItem.getDateMap().get("startDate");
			if (startDateFromWfItem!=null){
				startDateFromWfItem=startDateFromWfItem.getTime();
							
				if (ownerSet.size()>0){
					var ownerSetIterator=ownerSet.iterator();			
					while (ownerSetIterator.hasNext()){
						var ownerElement=ownerSetIterator.next();			
						var person=ownerElement.getPersonMap().get("ownerId");
						
						var ownerDepartmentPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
						ownerDepartmentPositionSearch.setPersonId(person.getId());
						ownerDepartmentPositionSearch.setDate(startDateFromWfItem);
						ownerDepartmentPositionSearch.setOrganizationUnitTypeDescription("department");
						ownerDepartmentPositionSearch.setDiscriminator("research");							
						var ownerDepartmentPositionSet = gaService.getPositionSearchList(ownerDepartmentPositionSearch, 0);
						var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(ownerDepartmentPositionSet, "research", "department");
						
						var ownerDepartmentPositionSetIterator=ownerDepartmentPositionSet.iterator();							
						while (ownerDepartmentPositionSetIterator.hasNext()){
							var position=ownerDepartmentPositionSetIterator.next();
							if (maxPriority == null || maxPriority.equals(position.getPriority())) {
								ownerDepartmentSet.add(position.getOrganizationUnit());														
								break;
							}
						}										
					}
				}
				if (ownerDepartmentSet.size()>0){
					if (orgUnitSet.size()>0){
			 			var orgUnitSetIterator=orgUnitSet.iterator();			
						while (orgUnitSetIterator.hasNext()){											
							var wfItemElement=orgUnitSetIterator.next();												
							var orgUnit=wfItemElement.getOrganizationUnitMap().get("ouId");
							internalOrganizationUnitSet.add(orgUnit);
						}
					}
				}
				
				if(!internalOrganizationUnitSet.containsAll(ownerDepartmentSet)){
					var nonMatchedDepartmentCollection=Packages.org.apache.commons.collections.CollectionUtils.subtract(ownerDepartmentSet, internalOrganizationUnitSet);
					var nonMatchedDepartmentCollectionIterator=nonMatchedDepartmentCollection.iterator();
					var nonMatchedDepartmentString="";
					var counter=0;
					while(nonMatchedDepartmentCollectionIterator.hasNext()){
						var nonMatchedDepartment=nonMatchedDepartmentCollectionIterator.next();
						if (counter++>0)
							nonMatchedDepartmentString+=", ";
						nonMatchedDepartmentString+=nonMatchedDepartment.getDescription();
					}
					var df =  Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");
					var dateAsString=df.format(startDateFromWfItem);
					errors.reject("error.proposal.multipleInternalOrganization.matchWithDepartmentOwnerNotFound", [nonMatchedDepartmentString], null);       								
				} 	
			}	
		

grantorValidatorProposal

			
			var grantorSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "grantor", wfService);
			if (grantorSet.size()<1)
				errors.reject("error.proposal.grantor.atLeast1");
		

currencyAndInternalContributionValidatorProposal

			
			var currency=object.getWfDictionaryMap().get("currency");
			var euroCurrency=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.dictionary.currency.euro");
			if (!euroCurrency){
				throw "Configuration variable ap.dictionary.currency.euro MUST BE DEFINED"; 								
			}
			if (currency && currency.getId()!=euroCurrency){
				if (!object.getNumberMap().get("internalContributionOriginalCurrency")){       										
					errors.rejectValue("numberMap[internalContributionOriginalCurrency]","error.proposal.funding.internalContributionOriginalCurrency.required");									
				}
				if (!object.getNumberMap().get("exchangeRate")){
					errors.rejectValue("numberMap[exchangeRate]","error.proposal.funding.exchangeRate.required");									
				}
				if (!object.getDateMap().get("exchangeRateDate")){
					errors.rejectValue("dateMap[exchangeRateDate]","error.proposal.funding.exchangeRateDate.required");									
				}
			}	       							
		

partnerAndGlobalCostValidatorProposal

			
			var coordinatorRoleId=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.role.main");
			var uniquePartnerRoleId=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.role.uniquePartner");
			
			var myOrganization=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.project.partner.myOrganization");
			if (coordinatorRoleId==null || myOrganization==null || uniquePartnerRoleId==null){
				throw "Configuration variables ap.project.partner.role.main, ap.project.partner.role.uniquePartner and ap.project.partner.myOrganization MUST BE DEFINED";
			} else {
				coordinatorRoleId=new Packages.java.lang.Integer(coordinatorRoleId);
				uniquePartnerRoleId=new Packages.java.lang.Integer(uniquePartnerRoleId);
				myOrganization=new Packages.java.lang.Integer(myOrganization);				
			}		
			var partnerSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement", "partner",wfService);
			var partnerSetIterator=partnerSet.iterator();
			var counterOtherPartner=0;
			var counterCoordinator=0;
			var counterUniquePartner=0;
			while (partnerSetIterator.hasNext()){
				var element=partnerSetIterator.next();			 
				var orgUnitRole = element.getWfDictionaryMap().get("partnerRole");
				var orgUnit = element.getOrganizationUnitMap().get("partnerId");
				if (coordinatorRoleId.equals(orgUnitRole.getId())){
					counterCoordinator++;
				} else 	if (uniquePartnerRoleId.equals(orgUnitRole.getId())){
					counterUniquePartner++;
				} else {
					counterOtherPartner++;
				}
				if(myOrganization.equals(orgUnit.getId()) && coordinatorRoleId.equals(orgUnitRole.getId())){
					
					if (!object.getNumberMap().get("globalContribution")){
						errors.rejectValue("numberMap[globalContribution]","error.proposal.funding.globalContribution.required");											
					}
					
					if (!object.getNumberMap().get("globalCost")){
						errors.rejectValue("numberMap[globalCost]","error.proposal.funding.globalCost.required");											
					}
					
					var currency=object.getWfDictionaryMap().get("currency");
					var euroCurrency=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.dictionary.currency.euro");
					if (!euroCurrency){
						throw "Configuration variable ap.dictionary.currency.euro MUST BE DEFINED"; 								
					}
					if (currency && currency.getId()!=euroCurrency){
						if (!object.getNumberMap().get("globalCostOriginalCurrency")){
							errors.rejectValue("numberMap[globalCostOriginalCurrency]","error.proposal.funding.globalCostOriginalCurrency.required");											
						}										
						
						if (!object.getNumberMap().get("globalContributionOriginalCurrency")){
							errors.rejectValue("numberMap[globalContributionOriginalCurrency]","error.proposal.funding.globalContributionOriginalCurrency.required");											
						}
					}
				}			
			}
			if (counterCoordinator>1){									
				errors.reject("error.proposal.partner.tooManyMain");
			} else if (counterUniquePartner>1){									
				errors.reject("error.proposal.partner.tooManyUniquePartner");
			} else if (partnerSet.size()>0){
				if (counterCoordinator>0 && counterUniquePartner>0){
					errors.reject("error.proposal.partner.coordinatorAndUniquePartner");
				} else if (counterOtherPartner>0 && counterCoordinator==0){
					errors.reject("error.proposal.partner.missingMain");
				} else if (counterOtherPartner>0 && counterUniquePartner>0){
					errors.reject("error.proposal.partner.otherPartnerAndUniquePartner");
				} else if (counterOtherPartner==0 && counterCoordinator>0){
					errors.reject("error.proposal.partner.coordinatorAndNoOtherPartner");
				}				
			}	       							
	       							
		

wfStartLogicPublicEngagement

			if(wfItem.getBooleanMap().get("periodicEvent")==null){
				wfItem.getBooleanMap().put("periodicEvent",false);
			}					
			if(wfItem.getBooleanMap().get("istitutionalInitiative")==null){
				wfItem.getBooleanMap().put("istitutionalInitiative",false);
			}
			if(wfItem.getBooleanMap().get("evaluationEnable")==null){
				wfItem.getBooleanMap().put("evaluationEnable",false);
			}			
			if(wfItem.getNumberMap().get("externalFinancing")==null){
				wfItem.getNumberMap().put("externalFinancing",new java.math.BigDecimal("0"));
			}
			if(wfItem.getNumberMap().get("totalBudget")==null){
				wfItem.getNumberMap().put("totalBudget", new java.math.BigDecimal("0"));
			}	
			if(wfItem.getNumberMap().get("numTotalDay")==null){
				wfItem.getNumberMap().put("numTotalDay", new java.math.BigDecimal("1"));
			}
			if(wfItem.getBooleanMap().get("personOrDepartment")!=null){			
				wfItem.getBooleanMap().put("personOrDepartment",null);
			}			
			true;
		

wfStartLogicPublicEngagementAcademicAreaFromOwner

			
			//logica di start che va a popolare l'academicArea (scientificAreasInvolved Aree scientifiche coinvolte )
			//con l'area ministeriale estratta dall'owner in start
			//lavora in coppia con la logica di save per gli owner(?)
			
			//devo usare per forza il metodo lungo perchè l'owner è già stato spostato negli element
			var ownerElementSet = wfItem.getWfItemElementSet("owner");
			var ownerElementSetIterator = ownerElementSet.iterator();
			
			while(ownerElementSetIterator.hasNext()){
			
				var ownerElement = ownerElementSetIterator.next();
				var person = gaService.getPerson(ownerElement.getPersonMap().get("ownerId").getId());
				
				var positionLastSet = person.getPositionLastSet();
				var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionLastSet, "research", "academicArea");
				positionLastSetIterator = positionLastSet.iterator();
				
				while (positionLastSetIterator.hasNext()){
					var position = positionLastSetIterator.next();					
					if (maxPriority == null || maxPriority.equals(position.getPriority())) {
					
						if ("research".equals(position.getDiscriminator()) 
							&& "academicArea".equals(position.getOrganizationUnit().getOrganizationUnitType().getDescription())) {
							
								//log.error("FOUND ONE!");
							
								var saiElement = new Packages.it.cilea.wf.model.WfItemElement();
								saiElement.setDiscriminator("scientificAreasInvolved");
								saiElement.setWfItemId(wfItem.getId());
								saiElement.getOrganizationUnitMap().put("ouId", position.getOrganizationUnit());
								wfService.saveOrUpdate(saiElement);
								wfItem.getWfItemElementSet().add(saiElement);
								
								break;
						}
					}
				}
			}
			
			true;
		

validatorDepartmentPublicEngagement
Viene controllato che la persona aggiunta sia all'interno del dipertimento questo è il messaggio di errore: "Il responsabile dell'iniziativa deve afferire ad un dipartimento. Scegliere un responsabile con un'afferenza valida." . Questa condizione viene applicata se nella tabella di configurazione di MA è presente la variabile "ap.pen.owner.internalOrganizationUnit.mandatory" viene messa a true. Se non è presente la variabile: questa validazione non è applicata.
Dal punto di vista del modello dati si tratta degli elementi di tipo owner
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

			var personOrDepartment =wfItem.getBooleanMap().get("personOrDepartment");
			if (personOrDepartment==true){			
				var person=wfItem.getPersonMap().get("owner");
				if(person!=null){
					var mandatory=Packages.it.cilea.wf.util.WfUtil.getMandatory(object,"owner");
					if(mandatory){					
						person=gaService.getPerson(person.getId());				
						var startDate=wfItem.getDateMap().get("startDate");
						if(startDate!=null){
							//setto il positionSearch in modo da trovare se ho delle position di ricerca per quella data
							var ownerPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();							
							ownerPositionSearch.setPersonId(person.getId());
							ownerPositionSearch.setDate(startDate.getTime());
							ownerPositionSearch.setOrganizationUnitTypeDescription("department");
							ownerPositionSearch.setDiscriminator("research");
							var ownerPositionSet = gaService.getPositionSearchList(ownerPositionSearch, 0);
							if(ownerPositionSet.isEmpty()){
								  errors.reject("error.publicEngagement.start.organizationUnitMap.required");
							}
						}else {
							errors.reject("error.startDate.required");
						}
					}		
				}
			}
		

ownerStartValidatorPublicEngagement
Questa validazione controlla che esista almeno un Responsabile scientifico e Dipartimento obbligatorio nel tab "Dati generali".
Dal punto di vista del modello dati si tratta degli elementi di tipo object
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

			
			if (object.getId()==null){		
				var personOrDepartment =object.getBooleanMap().get("personOrDepartment");					
				if  ((personOrDepartment==true)&&(object.getPersonMap().get("owner")==null)){
					errors.rejectValue("personMap[owner]","error.publicEngagement.owner.required");					
				}else if ((personOrDepartment==false)&&(object.getOrganizationUnitMap().get("ouId")==null)){			
					errors.rejectValue("organizationUnitMap[ouId]","error.publicEngagement.organizationUnitMap.required");
				}
			}			
		

checkToolEvaluation
Viene controllato che siano presenti nella Public Engagement gli strumenti di valutazione obbligatori, questo è l'errore che viene visualizzato: "Strumenti di valutazione obbligatori" nel tab "Dati generali".
Dal punto di vista del modello dati si tratta degli elementi di tipo evaluationTool
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

			var isToolEnable=object.getBooleanMap().get("evaluationEnable");
			var listEvaluation=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "evaluationTool", wfService);
			if ((isToolEnable==true)&&(listEvaluation.size()==0)){
			errors.rejectValue("booleanMap[evaluationEnable]","error.publicEngagement.toolEvaluationEngagement.required");				
		}

suardDepartmentHelpdeskInitiativeValidatorPublicEngagement
Viene controllato che siano presenti nella Public Engagement almeno un dipartimento relativo all'inziativa SUARD.
Dal punto di vista del modello dati si tratta degli elementi di tipo internalOrganizationUnit
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

			var suardUniversityInitiative =wfItem.getBooleanMap().get("suardUniversityInitiative");
			if (suardUniversityInitiative==false){			
				var actualDipartment =object.getOrganizationUnitMap().get("suardDepartmentInitiative");	
				if(actualDipartment==null){
					errors.reject("error.publicEngagement.organizationUnitMap.required");
				}else { 
					var wfItem= wfService.getWfItem(object.getWfItemId());			
					var dipartementList=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);					
					var departmentWfElementSetIterator=dipartementList.iterator();
					var isPresent=false;		
					while(departmentWfElementSetIterator.hasNext()){
						var department=departmentWfElementSetIterator.next();
						var departmentOwner =department.getOrganizationUnitMap().get("ouId");
				        if(actualDipartment.getId().equals(departmentOwner.getId())){
							isPresent=true;
							break;
						}
					}
					if(false==isPresent){
						errors.reject("error.publicEngagement.notallowed.suardDepartmentInitiative");
					}
				}
			}
		

suardDepartmentInitiativeValidatorPublicEngagement
Viene controllato che siano presenti nella Public Engagement almeno un dipartimento relativo all'inziativa SUARD.
Dal punto di vista del modello dati si tratta degli elementi di tipo internalOrganizationUnit
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

			var suardUniversityInitiative =wfItem.getBooleanMap().get("suardUniversityInitiative");
			if (suardUniversityInitiative==false){			
				var actualDipartment =object.getOrganizationUnitMap().get("suardDepartmentInitiative");	
				if(actualDipartment==null){
					errors.reject("error.publicEngagement.organizationUnitMap.required");
				}else { 
					var wfItem= wfService.getWfItem(object.getWfItemId());			
					var dipartementList=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);					
					var departmentWfElementSetIterator=dipartementList.iterator();
					var isPresent=false;		
					while(departmentWfElementSetIterator.hasNext()){
						var department=departmentWfElementSetIterator.next();
						var departmentOwner =department.getOrganizationUnitMap().get("ouId");
				        if(actualDipartment.getId().equals(departmentOwner.getId())){
							isPresent=true;
							break;
						}
					}
					if(false==isPresent){
						errors.reject("error.publicEngagement.notallowed.suardDepartmentInitiative");
					}
				}
			}else {
				errors.reject("error.publicEngagement.notallowed");
			}
		

deleteValidatorParentDetectorPublicEngagement
validator di delete che impedisce l'eliminazione dell'item nel caso in cui sia collegato ad altri publicEngagement (sia loro 'figlio')
Dal punto di vista del modello dati si tratta degli elementi di tipo wfItem
Per maggiori dettagli cfr. excel modello dati dell'entità Contratto

			
			var wfItem = wfService.getWfItem(object.getWfItemId());
			var identifier = wfItem.getIdentifier();
			
			if(!wfItem.getChildWfItemLinkSet("publicEngagementLink").isEmpty())
				errors.reject("error.publicEngagement.childDetected");
			
		

deleteValidatorChildDetectorPublicEngagement
Validator di delete che impedisce l'eliminazione dell'item nel caso in cui sia collegato ad altri publicEngagement (sia loro 'padre')
Dal punto di vista del modello dati si tratta degli elementi di tipo wfItem
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

			
			var wfItem = wfService.getWfItem(object.getWfItemId());
			var identifier = wfItem.getIdentifier();
			
			if(!wfItem.getParentWfItemLinkSet("publicEngagementLink").isEmpty())
				errors.reject("error.publicEngagement.parentDetected");
			
		

periodicityValidatorPublicEngagement
Validator di forward che impedisce l'avanzamento se l'evento è periodico ma non è indicata la periodicità
Dal punto di vista del modello dati si tratta degli elementi di tipo wfItemData
Nel dettagio controlla i campi command.booleanMap[periodicEvent] e command.wfDictionaryMap[periodicity]
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

			
			var wfItem = wfService.getWfItem(object.getWfItemId());
			var periodicEvent = wfItem.getBooleanMap().get("periodicEvent");
			
			if (periodicEvent != null && periodicEvent == true){
				if(wfItem.getWfDictionaryMap().get("periodicity") == null)
					errors.reject("error.publicEngagement.periodicEvent.periodicityNotIndicated");
			}
			
		

scientificAreasInvolvedValidatorPublicEngagement
Questa validazione controlla che esista almeno un'Area scientifica coinvolta nella sezione "Aree scientifiche coinvolte" nel tab "Classificazioni".
Dal punto di vista del modello dati si tratta degli elementi di tipo WfItemElement-scientificAreasInvolved
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

			
			var scientificAreasInvolvedSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "scientificAreasInvolved", wfService);
			if(scientificAreasInvolvedSet.isEmpty()){
				errors.reject("error.publicEngagement.scientificAreasInvolved.atLeast1");
			}	
			
		

transitionCommentValidatorPublicEngagement
Questa validazione controlla che venga popolata la motivazione di transizione di stato.
Essendo posta come validazione di enter in Bozza, è necessario eseguire un controllo più fine per attivarla.
Dal punto di vista del modello dati si tratta degli elementi di tipo WfItemData
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

		
			//si deve attivare ogni volta che si TORNA in bozza
			if(object.getIntegerMap().get("wfItemTypeIdPreviousValue") != null){
				
				if(object.getStringMap().get("transitionComment") == null){
					//uso la rejectValue così mi segna il campo da compilare e si attiva la visualizzazione
					errors.rejectValue("stringMap[transitionComment]","error.publicEngagement.transitionComment.required");
				}	
			}
			
		

impactIndicatorsValidatorPublicEngagement
Questa validazione controlla che non venga caricata la stessa tipologia di impactIndicators più volte inutilmente.
Dal punto di vista del modello dati si tratta degli elementi di tipo WfItemElement
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

			
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement = object;
			var wfItem = wfService.getWfItem(wfItemElement.getWfItemId());
			
			var impactIndicatorType = wfItemElement.getWfDictionaryMap().get("dictionary");
			
			if(impactIndicatorType != null){
			
				var impactIndicatorsSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "impactIndicators", wfService);	
				var impactIndicatorsSetIterator = impactIndicatorsSet.iterator();
				
				while(impactIndicatorsSetIterator.hasNext()){
				
					var impactIndicatorsElement = impactIndicatorsSetIterator.next();
					
					//controllo per non confrontare lo stesso oggetto
					if(wfItemElement.getId() != impactIndicatorsElement.getId()){
						
						var dictionary = impactIndicatorsElement.getWfDictionaryMap().get("dictionary");
						
						if(impactIndicatorType.getId() == dictionary.getId()){
							errors.reject("error.publicEngagement.impactIndicators.typeAlreadyPresent");
						}
					}
				}		
			}

			
		

publicInvolvedDuplicatedValidatorPublicEngagement
Questa validazione controlla che non venga caricata la stessa tipologia di publicInvolved più volte inutilmente.
Dal punto di vista del modello dati si tratta degli elementi di tipo WfItemElement
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

			
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement = object;
			var wfItem = wfService.getWfItem(wfItemElement.getWfItemId());
			
			var publicInvolvedType = wfItemElement.getWfDictionaryMap().get("dictionary");
			
			if(publicInvolvedType != null){
			
				var publicInvolvedSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "publicInvolved", wfService);	
				var publicInvolvedSetIterator = publicInvolvedSet.iterator();
				
				while(publicInvolvedSetIterator.hasNext()){
				
					var publicInvolvedElement = publicInvolvedSetIterator.next();
					
					//controllo per non confrontare lo stesso oggetto
					if(wfItemElement.getId() != publicInvolvedElement.getId()){
						
						var dictionary = publicInvolvedElement.getWfDictionaryMap().get("dictionary");
						
						if(publicInvolvedType.getId() == dictionary.getId()){
							errors.reject("error.publicEngagement.publicInvolved.typeAlreadyPresent");
						}
					}
				}		
			}
			
		

specificOtherValuePopulatedValidatorPublicEngagement
Questa validazione controlla che venga popolata il campo per specificare più informazioni nel caso venga selezionata la tipologia Altro.
Dal punto di vista del modello dati si tratta degli elementi di tipo WfItemElementData
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

	
			
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement = object;
			var wfItem = wfService.getWfItem(wfItemElement.getWfItemId());
			
			var publicInvolvedType = wfItemElement.getWfDictionaryMap().get("dictionary");
			
			if(publicInvolvedType != null){
			
				//log.error("publicInvolvedType: "+publicInvolvedType);
				
				publicInvolvedType = wfService.getWfDictionary(publicInvolvedType.getId());
			
				var publicInvolvedTypeCode = publicInvolvedType.getInternalSourceIdentifier();
				//log.error("publicInvolvedType-Code: "+publicInvolvedTypeCode);
				
				if(Packages.org.apache.commons.lang.StringUtils.equals("publicInvolvedPublicEngagement.other", publicInvolvedTypeCode) &&
					wfItemElement.getStringMap().get("specificOtherValue") == null){
					errors.rejectValue("stringMap[specificOtherValue]","error.publicEngagement.publicInvolved.specificOtherValue.required");
				}	
			}	
			
		

publicInvolvedAtLeastOneValidatorPublicEngagement
Questa validazione controlla che esista almeno un'Area scientifica coinvolta nella sezione "Aree scientifiche coinvolte" nel tab "Classificazioni".
Dal punto di vista del modello dati si tratta degli elementi di tipo WfItemElement-scientificAreasInvolved
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

			
			var itemTypeIdentifier = object.getWfItemType().getIdentifier();
			
			if(Packages.org.apache.commons.lang.StringUtils.equals("PEN.FORMAZIONE-COMUNICAZIONE", itemTypeIdentifier)){
				
				var publicInvolvedSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "publicInvolved", wfService);
				if(publicInvolvedSet.isEmpty()){
					errors.reject("error.publicEngagement.publicInvolved.atLeast1");
				}
			}	
			
		

addScientificAreaInvolvedFromNewOwnerValidatorPublicEngagement
Questa "validazione" va a popolare la sezione "Aree scientifiche coinvolte" nel tab "Classificazioni" ogni volta che viene aggiunto un nuovo owner.
Dal punto di vista del modello dati si tratta degli elementi di tipo WfItemElement-scientificAreasInvolved
Per maggiori dettagli cfr. excel modello dati dell'entità PublicEngagement

		
			if(!errors.hasErrors()){
			
				//inutile, ma mi serve per ricordarmi il contesto
				var wfItemElement = object;							
				var wfItem = wfService.getWfItem(wfItemElement.getWfItemId()); 
				var fragmentInfo = Packages.it.cilea.core.fragment.util.FragmentUtil.getFragmentableInfo(wfItemElement);
				var newOwnerToAdd = wfItemElement.getPersonMap().get(fragmentInfo.getDiscriminator()+"Id");
				var person = gaService.getPerson(newOwnerToAdd.getPersonId());
				
				var positionLastSet = person.getPositionLastSet();
				var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionLastSet, "research", "academicArea");
				positionLastSetIterator = positionLastSet.iterator();
				
				while (positionLastSetIterator.hasNext()){
					var position = positionLastSetIterator.next();					
					if (maxPriority == null || maxPriority.equals(position.getPriority())) {
					
						if ("research".equals(position.getDiscriminator()) 
							&& "academicArea".equals(position.getOrganizationUnit().getOrganizationUnitType().getDescription())) {
							
							//log.error("FOUND ONE!");
							//ora che ho trovato l'academicArea, vado a vedere se non è già presente
							
							var scientificAreasInvolvedElementSet = wfItem.getWfItemElementSet("scientificAreasInvolved");
							var scientificAreasInvolvedElementSetIterator = scientificAreasInvolvedElementSet.iterator();
							var alreadyAdded = false;
							
							while(scientificAreasInvolvedElementSetIterator.hasNext()){
							
								var scientificAreasInvolvedElement = scientificAreasInvolvedElementSetIterator.next();
								var orgUnit = scientificAreasInvolvedElement.getOrganizationUnitMap().get("ouId");
								if(orgUnit.getOrganizationUnitId() == position.getOrganizationUnitId()){
									alreadyAdded = true;
								}
							}
							
							//se alla fine non l'ho trovata, allora la inserisco
							if(!alreadyAdded){
								
								var saiElement = new Packages.it.cilea.wf.model.WfItemElement();
								saiElement.setDiscriminator("scientificAreasInvolved");
								saiElement.setWfItemId(wfItem.getId());
								saiElement.getOrganizationUnitMap().put("ouId", position.getOrganizationUnit());
								wfService.saveOrUpdate(saiElement);
								wfItem.getWfItemElementSet().add(saiElement);
								
								//UTILIZZARE QUESTO Packages.it.cilea.core.fragment.util.FragmentUtil.addNewFragment(ouIe, wfService);	
								
								break;
							}	
						}
					}
				}
			
			}
			
		

wfIdentityLogicMultipleHeadOfDepartmentPublicEngagementPermissionsJs
Questa è una permissions logic che costruisce dinamicamente i permessi per i publicEngagement per i Team Dipartimentali (headOfDepartment).
Viene eseguita ad ogni salvataggio e costruisce le permissions dei singoli dipartimenti in base al loro ruolo.

		
			var wfTask = object;
			var wfItem = wfService.getWfItem(wfTask.getWfItemId());
			var permissions = "r";			
			var isOnlyRead = true;
			
			var internalOrganizationUnitWfItemElementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem,
				"it.cilea.wf.model.WfItemElement", "internalOrganizationUnit", wfService);
				
			//log.error("xxx got ouSet");			

			//recupero l'unità organizzativa associata (dipartimento) all'identity/team di questo task
			var organizationUnitFromIdentity = Packages.it.cilea.ga.util.GaUtil.getOrganizationUnitFromIdentyForDepartment(gaAuthorizationService.getIdentity(wfTask.getIdentityId()), gaService);
			
			//log.error("xxx got organizationUnitFromIdentity: " + organizationUnitFromIdentity.getDescription());
			
			var isManagerPresent = Packages.it.cilea.wf.util.WfUtil.isRoleIdPresent("roleId", "ouRolePublicEngagement.manager", internalOrganizationUnitWfItemElementSet);
			
			var hasOrgUnitPowerPermissions = false;
			
			if(Packages.java.lang.Boolean.FALSE.equals(isManagerPresent)){
				
				var isPartecipantPresent = Packages.it.cilea.wf.util.WfUtil.isRoleIdPresent("roleId", "ouRolePublicEngagement.participant", internalOrganizationUnitWfItemElementSet);
				
				if(Packages.java.lang.Boolean.FALSE.equals(isPartecipantPresent)){
					
					var isAfferentPresent = Packages.it.cilea.wf.util.WfUtil.isRoleIdPresent("roleId", "ouRolePublicEngagement.afferent", internalOrganizationUnitWfItemElementSet);
					
					if(Packages.java.lang.Boolean.FALSE.equals(isAfferentPresent)){
						
						//log.error("xxx nothing is present");
						//altri ruoli non previsti
						hasOrgUnitPowerPermissions = false;
						
					}else{
						//log.error("xxx isAfferentPresent");
						hasOrgUnitPowerPermissions = Packages.it.cilea.wf.util.WfUtil.hasOrgUnitPowerPermissions("ouId", organizationUnitFromIdentity.getId(), "roleId", "ouRolePublicEngagement.afferent", internalOrganizationUnitWfItemElementSet);
					}
					
				}else{
					//log.error("xxx isPartecipantPresent");
					hasOrgUnitPowerPermissions = Packages.it.cilea.wf.util.WfUtil.hasOrgUnitPowerPermissions("ouId", organizationUnitFromIdentity.getId(), "roleId", "ouRolePublicEngagement.participant", internalOrganizationUnitWfItemElementSet);
				}
				
			}else{
				//log.error("xxx isManagerPresent");
				hasOrgUnitPowerPermissions = Packages.it.cilea.wf.util.WfUtil.hasOrgUnitPowerPermissions("ouId", organizationUnitFromIdentity.getId(), "roleId", "ouRolePublicEngagement.manager", internalOrganizationUnitWfItemElementSet);
			}

			//log.error("xxx hasOrgUnitPowerPermissions: " + hasOrgUnitPowerPermissions);
			
			/*
			draft	crwfd
			approved	rf
			submitted	rwf
			reopened	rwfd
			rejected	rfd
			preapproval	r
			concluded	r
			*/
			
			switch(String(wfItem.getWfState().getDescription())){
				case "draft": 
					if(Packages.java.lang.Boolean.TRUE.equals(hasOrgUnitPowerPermissions)) 
						permissions="crwfd";
					else 
						permissions="r";
				break;
				
				case "approved": 
					if(Packages.java.lang.Boolean.TRUE.equals(hasOrgUnitPowerPermissions)) 
						permissions="rwf";
					else 
						permissions="r";
				break;
				
				case "submitted": 
					if(Packages.java.lang.Boolean.TRUE.equals(hasOrgUnitPowerPermissions))
						permissions="rwf";
					else 
						permissions="r";
				break;
				
				case "reopened": 
					if(Packages.java.lang.Boolean.TRUE.equals(hasOrgUnitPowerPermissions))
						permissions="rwf";
					else 
						permissions="r";
				break;
				
				case "rejected": 
					if(Packages.java.lang.Boolean.TRUE.equals(hasOrgUnitPowerPermissions))
						permissions="rwf";
					else 
						permissions="r";
				break;
				
				/*
				case "preapproval": 
					if(Packages.java.lang.Boolean.TRUE.equals(hasOrgUnitPowerPermissions))
						permissions="rwf";
					else 
						permissions="r";
				break;
				
				case "concluded": 
					if(Packages.java.lang.Boolean.TRUE.equals(hasOrgUnitPowerPermissions))
						permissions="rwf";
					else 
						permissions="r";
				break;
				*/
				
				default:
					permissions="r";
				break;
				
					
			}
			
			//log.error("xxx permissions: " + permissions);
			wfTask.setPermissions(permissions);
		
		

wfActionLogicEnterWorkgroupOwnerMailSender

			X={
			subjectLabel:'label.ap.workgroup.mail.subject',
			textLabel:'label.ap.workgroup.mail.text',
			sendEnable:'ap.itemType.wkg.mail.enable',
			htmlEnable:'ap.itemType.wkg.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleOwners',
			to:'',
			from:''
			}; X;
		

wfActionLogicEnterWorkgroupHeadOfDepartmentMailSender

			X={
			subjectLabel:'label.ap.workgroup.mail.subject',
			textLabel:'label.ap.workgroup.mail.text',
			sendEnable:'ap.itemType.wkg.mail.enable',
			htmlEnable:'ap.itemType.wkg.mail.html.enable',
			identityLogic:'wfIdentityLogicMultipleHeadOfDepartment',
			to:'',
			from:''
			}; X;
		

laboratoryValidatorWorkgroup
Validazione che controlla che se esiste almeno un laboratorio collegato al gruppo di lavoro, questo laboratorio deve essere in stato "Approved" o in stato "Reopened", altrimenti lancia un errore.
Dal punto di vista del modello dati si tratta degli elementi di tipo workgroupLaboratoryLink
Per maggiori dettagli cfr. excel modello dati dell'entità Gruppi di Lavoro

			
			//ricavo dal fragment dei laboratory
			var laboratorySet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getChildWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "workgroupLaboratoryLink", wfService);
			//controllo banale, controllo che ci sia almeno un link, sennò non vado avanti
			if(laboratorySet.size()>0){
			
				//ricavo l'iteratore lo uso per ciclare il set
				var laboratorySetIterator = laboratorySet.iterator();
				while( laboratorySetIterator.hasNext() ){
				
					//ricavo il singolo link e prendo il child che è il laboratory
					var laboratoryLinkElement = laboratorySetIterator.next();
					var laboratory= laboratoryLinkElement.getChild();
					//poi ricavo il suo stato e controllo che sia in approved
					var laboratoryState = laboratory.getWfState().getDescription();
					
					if(!(Packages.org.apache.commons.lang.StringUtils.equals("approved", laboratoryState) || Packages.org.apache.commons.lang.StringUtils.equals("reopened", laboratoryState))){
						//se non è approved o reopened allora lancia l'errore
						errors.reject("error.workgroup.laboratory.mustBeApproved");
					}
					
				}
			
			}
		

equipmentValidatorWorkgroup
Validazione che controlla che se esiste almeno una Grande Attrezzatura collegata al gruppo di lavoro, questa Attrezzatura deve essere in stato "Approved" o in stato "Reopened", altrimenti lancia un errore.
Dal punto di vista del modello dati si tratta degli elementi di tipo workgroupEquipmentLink
Per maggiori dettagli cfr. excel modello dati dell'entità Gruppi di Lavoro

			
			//ricavo dal fragment dei equipment
			var equipmentSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getChildWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "workgroupEquipmentLink", wfService);
			//controllo banale, controllo che ci sia almeno un link, sennò non vado avanti
			if(equipmentSet.size()>0){
			
				//ricavo l'iteratore lo uso per ciclare il set
				var equipmentSetIterator = equipmentSet.iterator();
				while( equipmentSetIterator.hasNext() ){
				
					//ricavo il singolo link e prendo il child che è il equipment
					var equipmentLinkElement = equipmentSetIterator.next();
					var equipment= equipmentLinkElement.getChild();
					//poi ricavo il suo stato e controllo che sia in approved
					var equipmentState = equipment.getWfState().getDescription();
					
					 if(!(Packages.org.apache.commons.lang.StringUtils.equals("approved", equipmentState) || Packages.org.apache.commons.lang.StringUtils.equals("reopened", equipmentState))){
						//se non è approved o reopened allora lancia l'errore
						errors.reject("error.workgroup.equipment.mustBeApproved");
					}
					
				}
			
			}
		

selfLinkedWorkgroupValidator
Validazione che controlla che, mentre viene collegato ad altri gruppi di lavoro, il gruppo non venga collegato in un rapporto padre-figlio a se stesso
Dal punto di vista del modello dati si tratta degli elementi di tipo workgroupLink
Per maggiori dettagli cfr. excel modello dati dell'entità Gruppi di Lavoro

            
            //ricavo dal fragment dei workgroup
            var workgroupSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getChildWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "workgroupLink", wfService);
            //controllo banale, controllo che ci sia almeno un link, sennò non vado avanti
            if(workgroupSet.size()>0){
            
                //ricavo l'iteratore lo uso per ciclare il set
                var workgroupSetIterator = workgroupSet.iterator();
                while( workgroupSetIterator.hasNext() ){
                
                    //ricavo il singolo link e prendo il child che è il workgroup collegato
                    var workgroupLinkElement = workgroupSetIterator.next();
                    var workgroup= workgroupLinkElement.getChild();
                    
                    if(object.getWfItemId()==workgroup.getWfItemId()){
                        //se sono uguali allora lancia l'errore
                        errors.reject("error.workgroup.workgroupLink.linkedToItself");
                    }
                }
            }            
        

approvedWorkgroupValidator
Validazione che controlla che, mentre viene collegato ad altri gruppi di lavoro, il Gruppo non venga collegato a Gruppi che non siano in stato "approved" o "reopened",
Dal punto di vista del modello dati si tratta degli elementi di tipo workgroupLink
Per maggiori dettagli cfr. excel modello dati dell'entità Gruppi di Lavoro

            
            //ricavo dal fragment dei workgroup
            var workgroupSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getChildWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "workgroupLink", wfService);
            //controllo banale, controllo che ci sia almeno un link, sennò non vado avanti
            if(workgroupSet.size()>0){
            
                //ricavo l'iteratore lo uso per ciclare il set
                var workgroupSetIterator = workgroupSet.iterator();
                while( workgroupSetIterator.hasNext() ){
                
                    //ricavo il singolo link e prendo il child che è il workgroup collegato
                    var workgroupLinkElement = workgroupSetIterator.next();
                    var workgroup= workgroupLinkElement.getChild();
                   //poi ricavo il suo stato e controllo che sia in approved o reopened
                    var workgroupState= workgroup.getWfState().getDescription();
                    
                    if(!(Packages.org.apache.commons.lang.StringUtils.equals("approved", workgroupState) || Packages.org.apache.commons.lang.StringUtils.equals("reopened", workgroupState))){
						//se non è approved o reopened allora lancia l'errore
						errors.reject("error.workgroup.workgroupLink.mustBeApproved");
					}
                }
            }            
        

projectValidatorWorkgroup
Validazione che controlla che se esiste almeno una Progetto collegato al gruppo di lavoro, questo Progetto deve essere in uno stato che è contenuto nella variabile "ap.wkg.workgroupProjectLink.csvAllowedProjectState" altrimenti lancia un errore.
Dal punto di vista del modello dati si tratta degli elementi di tipo workgroupProjectLink
Per maggiori dettagli cfr. excel modello dati dell'entità Gruppi di Lavoro

			
			//ricavo dal fragment dei project
			var projectSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getChildWfItemLinkSet", "it.cilea.wf.model.WfItemLink", "workgroupProjectLink", wfService);
			//controllo banale, controllo che ci sia almeno un link, sennò non vado avanti
			if(projectSet.size()>0){
				
				//variabile che mi servirà più tardi
				var configStatesArray=[];
				
				//controllo per vedere se è definita la variabile di configurazione con gli stati accettati
				var csvAllowedProjectState=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.wkg.workgroupProjectLink.csvAllowedProjectState");
				if (!csvAllowedProjectState){
					//nel caso non sia definita
					throw "Configuration variable ap.wkg.workgroupProjectLink.csvAllowedProjectState MUST BE DEFINED";
				}else{
					//vado a immettere in una lista tutti gli stati ricavati
					configStatesArray = csvAllowedProjectState.split(',');
				}
				
				//ricavo l'iteratore lo uso per ciclare il set
				var projectSetIterator = projectSet.iterator();
				while( projectSetIterator.hasNext() ){
				
					//ricavo il singolo link e prendo il child che è il project
					var projectLinkElement = projectSetIterator.next();
					var project = projectLinkElement.getChild();
					//poi ricavo il suo stato e controllo che sia in uno degli stati ricavati dalla config
					var projectState = project.getWfState().getDescription();
					
					//vado a confrontare lo stato del progetto con tutti quelli ricavati
					//se non è tra quelli in configurazione, scateno il messaggio di errore
					//variabile per controllo, viene rigenerata per ogni progetto collegato
					var isPermited=false;
					for(var i=0; i<configStatesArray.length; i++){
						if(Packages.org.apache.commons.lang.StringUtils.equals(configStatesArray[i], projectState))
							isPermited=true;
					}
					
					if(isPermited==false){
						//uso questo stratagemma visto che non conosco quanti stati possano essere accettati
						var arrayStatesNamesAllArray = [];
						var arrayStatesNamesAllString="";
						
						//ciclo i nomi degli stati permessi e vado a ricavare il loro nome 'normale'
						for(var i=0; i<configStatesArray.length; i++){
							if(i>0)
								arrayStatesNamesAllString+=", ";
							
							arrayStatesNamesAllString += Packages.it.cilea.core.util.MessageUtilConstant.messageUtil.findMessage("wfState." + configStatesArray[i]);
						}
						arrayStatesNamesAllArray.push(arrayStatesNamesAllString);
						errors.reject("error.workgroup.project.stateMustBeAccepted", arrayStatesNamesAllArray, null);
					}
				}
			}
		

emailValidator

			
			var wfItemElement=object;
			var contactTypeId=wfItemElement.getGaDictionaryMap().get("contactType").getId();
			var contactTypeDictionary=gaService.getGaDictionary(contactTypeId);
			if (contactTypeDictionary.getDescription().equals("mail")){
				var pattern = Packages.java.util.regex.Pattern
						.compile("^[_A-Za-z0-9-]+(\.[_A-Za-z0-9-]+)*@[\-A-Za-z0-9]+(\.[\-A-Za-z0-9]+)*(\.[A-Za-z]{2,})$");
				var matcher = pattern.matcher(wfItemElement.getStringMap().get("description"));
				if (!matcher.matches()) {
					errors.rejectValue("stringMap[description]", "error.workgroup.contact.mail.invalidValue");
				}
			}
		

ownerCannotAddOtherOnesValidator

			
			//ricavo dalla request l'utente loggato in quel momento
			//NOTA: in caso di loginAs restituisce l'user impersonato
			var personalUserName=request.getUserPrincipal().getName();
			var personId=gaService.getUser(personalUserName).getPersonId();
			
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement=object;
			//ricavo wfItem completo, non mi serve il fragment dato che non posso comunque 
			var wfItem= wfService.getWfItem(wfItemElement.getWfItemId()); 
			
			//cerco tra gli owner se c'è la persona al momento loggata
			var ownerWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","owner", wfService);
			var ownerWfElementSetIterator=ownerWfElementSet.iterator();
			
			while(ownerWfElementSetIterator.hasNext()){
				var ownerElement=ownerWfElementSetIterator.next();
				var owner=ownerElement.getPersonMap().get("ownerId");
				if(owner.getId()==personId){
					errors.reject("error.workgroup.owner.cannotAddOtherOnes");
				}
			}
		

ownerCannotDeleteOtherOnesValidator

			
			//ricavo dalla request l'utente loggato in quel momento
			//NOTA: in caso di loginAs restituisce l'user impersonato
			var personalUserName=request.getUserPrincipal().getName();
			var personId=gaService.getUser(personalUserName).getPersonId();
			
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement=object;
			//ricavo wfItem completo, non mi serve il fragment dato che non posso comunque 
			var wfItem= wfService.getWfItem(wfItemElement.getWfItemId()); 
			
			//cerco tra gli owner se c'è la persona al momento loggata
			var ownerWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","owner", wfService);
			var ownerWfElementSetIterator=ownerWfElementSet.iterator();
			
			while(ownerWfElementSetIterator.hasNext()){
				var ownerElement=ownerWfElementSetIterator.next();
				var owner=ownerElement.getPersonMap().get("ownerId");
				if(owner.getId()==personId){
					errors.reject("error.workgroup.owner.cannotDeleteOtherOnes");
				}
			}
		

internalRepresentativeCannotEditOwnersValidator

			
			//ricavo dalla request l'utente loggato in quel momento
			//NOTA: in caso di loginAs restituisce l'user impersonato
			var personalUserName=request.getUserPrincipal().getName();
			var personId=gaService.getUser(personalUserName).getPersonId();
			
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement=object;
			//ricavo wfItem completo, non mi serve il fragment dato che non posso comunque 
			var wfItem= wfService.getWfItem(wfItemElement.getWfItemId()); 
			
			//cerco tra gli internalRepresentative se c'è la persona al momento loggata
			var internalRepresentativeWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","internalRepresentative", wfService);
			var internalRepresentativeWfElementSetIterator=internalRepresentativeWfElementSet.iterator();
			
			while(internalRepresentativeWfElementSetIterator.hasNext()){
				var internalRepresentativeElement=internalRepresentativeWfElementSetIterator.next();
				var internalRepresentative=internalRepresentativeElement.getPersonMap().get("internalRepresentative");
				if(internalRepresentative.getId()==personId){
					errors.reject("error.workgroup.internalRepresentative.cannotEditOwners");
				}
			}
		

wfActionLogicSaveExCoordinatorToContributor

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveExCoordinatorToContributor

wfActionLogicSaveContributorDefault
Questa action logic serve per generare i task necessari per rendere visibile l'oggetto nella visione personale dei partecipanti.
I task vengono generati in automatico in fase di transizione da uno stato ad un altro.
Ci sono casi però dove vengono modificate delle informazioni senza effettuare nessuna transizione di stato come ad esempio il caso in cui venga aggiunto un nuovo partecipante ad un progetto che è già nello stato corretto.
Questa action logic, se agganciata in save, consente di generare i task per rendere visibile l'oggetto anche in visione personale del nuovo partecipante.

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveContributorDefault

wfActionLogicSaveTutorDefault

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveTutorDefault

wfActionLogicSaveOtherCoordinatorDefault

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveOtherCoordinatorDefault

wfActionLogicSaveDateHistory

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveDateHistory

wfActionLogicSaveInvolvedDepartment

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveInvolvedDepartment

wfActionLogicSaveProjectNazInternazDepartmentValidation

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveProjectNazInternazDepartmentValidation

wfActionLogicLoadNazInternaz

it.cilea.wf.surplus.logic.action.load.WfActionLogicLoadNazInternaz

wfActionLogicEnterSetForwardInConfirmedDate

if (wfItem.getDateMap().get('forwardInConfirmedDate')==null) wfItem.getDateMap().put('forwardInConfirmedDate',java.util.Calendar.getInstance());

wfActionLogicEnterSetForwardInCompliantDate

if (wfItem.getDateMap().get('forwardInCompliantDate')==null) wfItem.getDateMap().put('forwardInCompliantDate',java.util.Calendar.getInstance());

wfActionLogicSaveContributorInvitation

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveContributorInvitation

wfActionLogicSaveMultipleOrganizationUnit
Questa action logic serve per generare i task necessari per rendere visibile l'oggetto in visione dipartimentale.
I task vengono generati in automatico in fase di transizione da uno stato ad un altro.
Ci sono casi però dove vengono modificate delle informazioni senza effettuare nessuna transizione di stato come ad esempio il caso in cui venga aggiunto un dipartimento ad un progetto che è già nello stato corretto.
Questa action logic, se agganciata in save, consente di generare i task per rendere visibile l'oggetto anche in visione dipartimentale.

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveMultipleOrganizationUnit

wfActionLogicSaveMultipleOwner
Questa action logic serve per generare i task necessari per rendere visibile l'oggetto nella visione personale dei responsabili scientifici
I task vengono generati in automatico in fase di transizione da uno stato ad un altro.
Ci sono casi però dove vengono modificate delle informazioni senza effettuare nessuna transizione di stato come ad esempio il caso in cui venga aggiunto un nuovo responsabile scientifico ad un progetto che è già nello stato corretto.
Questa action logic, se agganciata in save, consente di generare i task per rendere visibile l'oggetto anche in visione personale del nuovo responsabile scientifico.

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveMultipleOwner

wfActionLogicSaveMultipleAdministrativeOwner
Questa action logic serve per generare i task necessari per rendere visibile l'oggetto nella visione personale dei referenti amministrativi
I task vengono generati in automatico in fase di transizione da uno stato ad un altro.
Ci sono casi però dove vengono modificate delle informazioni senza effettuare nessuna transizione di stato come ad esempio il caso in cui venga aggiunto un nuovo referente amministrativo ad un progetto che è già nello stato corretto.
Questa action logic, se agganciata in save, consente di generare i task per rendere visibile l'oggetto anche in visione personale del nuovo referente amministrativo.

it.cilea.wf.surplus.logic.action.save.WfActionLogicSaveMultipleAdministrativeOwner

wfActionLogicVersionize

it.cilea.wf.logic.WfActionLogicVersionize

wfActionLogicEnterMailSender
Questa action logic serve per inviare segnalazioni via mail ai vari attori del flusso.
TODO

wfStartLogicStandardIdentifier
Questa logica viene eseguita in fase di creazione di un nuovo oggetto.
Viene effetuata la costruzione dell'identificativo dell'oggetto seguendo le seguenti regole:
<CODICE>-<PROGRESSIVO>

Per maggiori dettagli cfr. excel modello dati dell'entità in questione e la tassonomia ap-item-type.xls
			var sourceItemTypeCode=wfService.getWfItemType(wfItem.getWfItemTypeId()).getCode();		
			var identifier=sourceItemTypeCode+"-";
						
			var sequenceName = "item_" + sourceItemTypeCode + "_seq";
			var counter = wfService.updateSequence(sequenceName);
				
			var counterString;
			if (counter < 10)
				counterString = "000" + counter;
			else if (counter < 100)
				counterString = "00" + counter;
			else if (counter < 1000)
				counterString = "0" + counter;
			else
				counterString = "" + counter;
			
			identifier+=counterString;			
			wfItem.setIdentifier(identifier);						
			

wfStartLogicYearFromProposalStartDateIdentifier
Questa logica viene eseguita in fase di creazione di un nuovo progetto.
Viene effetuata la costruzione dell'identificativo dell'oggetto seguendo le seguenti regole:
<ANNO>-<CODICE>-<PROGRESSIVO>

Per maggiori dettagli cfr. excel modello dati dell'entità Progetto e la tassonomia ap-item-type.xls
			var startDate=wfItem.getDateMap().get("proposalStartDate");
			var year=startDate.get(Packages.java.util.Calendar.YEAR);
			
			var yearString=new Packages.java.lang.Integer(year).toString();
			
			var sourceItemTypeCode=wfItem.getWfItemType().getCode();
			
			var identifier=yearString+"-"+sourceItemTypeCode+"-";
						
			var sequenceName = "item_" + sourceItemTypeCode + "_" + year + "_seq";
			var counter = wfService.updateSequence(sequenceName);
	
			var counterString;
			if (counter < 10)
				counterString = "000" + counter;
			else if (counter < 100)
				counterString = "00" + counter;
			else if (counter < 1000)
				counterString = "0" + counter;
			else
				counterString = "" + counter;
			
			identifier+=counterString;			
			wfItem.setIdentifier(identifier);
		

wfStartLogicYearFromStartDate
Questa logica viene eseguita in fase di creazione di un nuovo oggetto. Viene recuperato l'anno dalla data di inizio startDate

			var startDate=wfItem.getDateMap().get("startDate");
			var year=startDate.get(Packages.java.util.Calendar.YEAR);
			wfItem.setYear(new Packages.java.lang.Integer(year));									
			

wfStartLogicOwnerDependentIdentifier

		
			var person = null;
			var ownerElementSetIterator=wfItem.getWfItemElementMap().get("owner").iterator();
			var min = 0;
			while(ownerElementSetIterator.hasNext()){
				var element = ownerElementSetIterator.next()
				if(min == 0){
					min = element.getId;
					person = element.getPersonMap().get("ownerId");
				} else {
					if(min > element.getId){
						min = element.getId;
						person = element.getPersonMap().get("ownerId");
					}
				}
			}
			var startDate=wfItem.getDateMap().get("proposalStartDate");
			var year=startDate.get(Packages.java.util.Calendar.YEAR);
			var yearString=new Packages.java.lang.Integer(year).toString();
			yearString=yearString.substring(2);
			var sourceItemTypeCode=wfService.getWfItemType(wfItem.getWfItemTypeId()).getCode();

			var lastName=person.getLastName().replaceAll("\s", "");
			lastName=lastName.replaceAll("'", "");
			lastName=(lastName.length()>=4)?lastName.substring(0,4):lastName.substring(0,lastName.length());
			lastName=lastName.toUpperCase();
			var firstName=person.getFirstName().substring(0,1);
			firstName=firstName.toUpperCase();	
			var identifier=sourceItemTypeCode+yearString+firstName+lastName+"_";
			var paramMap = new Packages.java.util.HashMap();
			paramMap.put("identifier", identifier);
			paramMap.put("excludeIdentifier", identifier+"M");
			var count=searchBuilderTemplate.getSingleObject("getMaxItemCountForGivenIdentifier", paramMap);
			var countString="";
			if (count<9)
				countString+="0";			
			countString+=(count.intValue()+1);
			identifier+=countString;			
			
			wfItem.setIdentifier(identifier);						
			

wfStartLogicAcademicField2000
Questa logica viene eseguita in fase di creazione di un nuovo oggetto.
Recupera il responsabile scientifico (owner), estrae il SSD relativo all'ultimo rapporto di lavoro valido prioritario relativo al contesto ricerca ed aggancia questa informazione all'oggetto radice.

								
				var person=null;	
			    person=wfItem.getPersonMap().get("owner");			
				var person2 = gaService.getPerson(person.getId());
				var positionLastSet = person2.getPositionLastSet();											
				var maxPriority2 = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(positionLastSet, "research", "academicField2000");
				positionLastSetIterator=positionLastSet.iterator();											
				while (positionLastSetIterator.hasNext()){
					var position=positionLastSetIterator.next();					
					if (maxPriority2 == null || maxPriority2.equals(position.getPriority())) {
						if ("research".equals(position.getDiscriminator()) && "academicField2000"
									.equals(position.getOrganizationUnit().getOrganizationUnitType().getDescription())) {
								var ssdElement=new Packages.it.cilea.wf.model.WfItemElement();
								ssdElement.setDiscriminator("academicField2000");
								ssdElement.setWfItemId(wfItem.getId());
								ssdElement.getOrganizationUnitMap().put("organizationUnit", position.getOrganizationUnit());
								wfService.saveOrUpdate(ssdElement);
								wfItem.getWfItemElementSet().add(ssdElement);
								break;			
						}
					}
				}
								
				true;
			

wfStartLogicMultipleOwners

			//caricamento owner
			var person=wfItem.getPersonMap().get("owner");
			if (person!=null){
				var startDate=wfItem.getDateMap().get("startDate");
				person=gaService.getPerson(person.getId());
				var ownerElement=new Packages.it.cilea.wf.model.WfItemElement();
				ownerElement.setDiscriminator("owner");
				ownerElement.setWfItemId(wfItem.getId());
				ownerElement.getPersonMap().put("ownerId", person);
				ownerElement.getDateMap().put("startDate", startDate);
				Packages.it.cilea.wf.util.WfUtil.addRoleInElementIfDefined(wfItem, ownerElement, wfService);			
				wfService.saveOrUpdate(ownerElement);
				wfItem.getWfItemElementSet().add(ownerElement);			
				wfItem.getPersonMap().put("owner", null);
					
				//caricamento dipartimento con data
				var ownerDepartmentPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
				ownerDepartmentPositionSearch.setPersonId(person.getId());
				ownerDepartmentPositionSearch.setDate(startDate.getTime());
				ownerDepartmentPositionSearch.setOrganizationUnitTypeDescription("department");
				ownerDepartmentPositionSearch.setDiscriminator("research");
				var ownerDepartmentPositionSet = gaService.getPositionSearchList(ownerDepartmentPositionSearch, 0);
				var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(ownerDepartmentPositionSet, "research", "department");
				
				var ownerDepartmentPositionSetIterator=ownerDepartmentPositionSet.iterator();							
				while (ownerDepartmentPositionSetIterator.hasNext()){
					var position=ownerDepartmentPositionSetIterator.next();
					if (maxPriority == null || maxPriority.equals(position.getPriority())) {
						var internalOrganizationUnitElement=new Packages.it.cilea.wf.model.WfItemElement();
						internalOrganizationUnitElement.setDiscriminator("internalOrganizationUnit");
						internalOrganizationUnitElement.setWfItemId(wfItem.getId());
						internalOrganizationUnitElement.getOrganizationUnitMap().put("ouId", position.getOrganizationUnit());
						Packages.it.cilea.wf.util.WfUtil.addRoleInElementIfDefined(wfItem, internalOrganizationUnitElement, wfService);
						wfService.saveOrUpdate(internalOrganizationUnitElement);
						wfItem.getWfItemElementSet().add(internalOrganizationUnitElement);
						break;					
					}
				}
			}				
			true;
		

wfStartLogicMultipleInternalOrganizationUnits

			//caricamento internalOrganizationUnit			
			var internalOrganizationUnit=wfItem.getOrganizationUnitMap().get("ouId");
			if (internalOrganizationUnit!=null){
				internalOrganizationUnit=gaService.getOrganizationUnit(internalOrganizationUnit.getId());
				var internalOrganizationUnitElement=new Packages.it.cilea.wf.model.WfItemElement();						
				internalOrganizationUnitElement.setDiscriminator("internalOrganizationUnit");
				internalOrganizationUnitElement.setWfItemId(wfItem.getId());
				internalOrganizationUnitElement.getOrganizationUnitMap().put("ouId",internalOrganizationUnit);			
				Packages.it.cilea.wf.util.WfUtil.addRoleInElementIfDefined(wfItem, internalOrganizationUnitElement, wfService);
				wfService.saveOrUpdate(internalOrganizationUnitElement);
				wfItem.getWfItemElementSet().add(internalOrganizationUnitElement);
				wfItem.getOrganizationUnitMap().put("ouId", null);
			}			
			true;
		

wfStartLogicAdministrativeOwnerFromUser
Questa logica viene eseguita in fase di creazione di un nuovo oggetto.
Aggiunge il referente amministrativo all'oggetto che si sta creando.
Precisamente:

Ad esempio supponiamo la variabile di conf ap.prj.administrativeOwner.inheritFromLoggedUserIfResourcePresent=/DEPARTMENT.profile,/RESEARCH_DIVISION.profile.
Questo vuol dire che se un utente che appartiene a un team con profili dipartimentali o divisione ricerca effettua la creazione di un oggetto, verrà inserito lui stesso come referente amministrativo. Per maggiori dettagli cfr. excel modello dati dell'entità in questione.
			var typeForConfig;
			var itemType = wfService.getWfItemType(wfItem.getWfItemTypeId());
			if (!itemType.getParentWfItemTypeSet().isEmpty()) {
				var parentSetIterator = itemType.getParentWfItemTypeSet().iterator();
				while (parentSetIterator.hasNext()){
					var parent = parentSetIterator.next();
					if (!parent.getParentWfItemTypeSet().isEmpty()) {
						var parentParentSetIterator = parent.getParentWfItemTypeSet().iterator();
						while (parentParentSetIterator.hasNext()){
							var parentParent = parentParentSetIterator.next();
							typeForConfig = parentParent;
							break;
						}
					}
					break;
				}
			}
			var profiles = '';
			if(typeForConfig.getIdentifier() == 'CON' || typeForConfig.getIdentifier() == 'PRJ'){
				profiles = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap."+ typeForConfig.getIdentifier().toLowerCase() +".administrativeOwner.inheritFromLoggedUserIfResourcePresent");
				var profileArray = profiles.split(",");
				var gaUserDetail = Packages.it.cilea.ga.authorization.context.GaAuthorizationUserHolder.getUser();	
				for(i in profileArray){
					if(gaUserDetail.hasAuthorities(profileArray[i])){
						var administrativeOwnerElement = new Packages.it.cilea.wf.model.WfItemElement();
						administrativeOwnerElement.setDiscriminator("administrativeOwner");
						administrativeOwnerElement.setWfItemId(wfItem.getId());
						
						var person = gaService.getPerson(gaUserDetail.getPersonId())
						
						administrativeOwnerElement.getPersonMap().put("administrativeOwner", person);
						
						wfService.saveOrUpdate(administrativeOwnerElement);
						wfItem.getWfItemElementSet().add(administrativeOwnerElement);			
						
						break;
					}
				}
			}
					
			true;
		

multipleOwnerValidator
validator per controllare presenza di almeno un owner NEL FRAGMENT Per maggiori dettagli cfr. excel modello dati dell'entità in questione.

			
			var ownerWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","owner", wfService);
			if(ownerWfElementSet.isEmpty()){
				errors.reject("error.owner.required");
			}
			
		

intellectualPropertyOwnerValidator

			
			//non mi importa in che stato sono, vado sempre a controllare dove potrei trovare l'owner
			var ownerInMap = object.getPersonMap().get("owner");
			var ownerWfElementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","owner", wfService);
			
			if(ownerInMap==null){
				if(ownerWfElementSet.isEmpty())
					errors.reject("error.intellectualProperty.owner.required");
			}
			
		

startDateAndEndDateValidator
Questa validazione controlla che la date di inizio preceda la data di fine
Dal punto di vista del modello dati si tratta degli attributi startDate e endDate
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

		
			if(object.getDateMap().get("endDate") != null && object.getDateMap().get("startDate") != null){
				if(object.getDateMap().get("startDate").getTime().after(object.getDateMap().get("endDate").getTime())){
					errors.reject("error.date.startDateEndDateNotCompatible");					
				}			
			}
		

startDateOfElementAfterStartDateOfItemValidator

			var wfItemElementStartDate=object.getDateMap().get("startDate");
			var wfItemStartDate=object.getWfItem().getDateMap().get("startDate");
			var wfItemEndDate=object.getWfItem().getDateMap().get("endDate");
			
			var formatter =  Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");						
			
			if( wfItemElementStartDate!= null && wfItemStartDate && (wfItemElementStartDate.before(wfItemStartDate) || (wfItemEndDate!=null && wfItemElementStartDate.after(wfItemEndDate)))  ){
				var suffixMessage=" - ";
				if (wfItemEndDate!=null){
					suffixMessage+=formatter.format(wfItemEndDate.getTime());
				} else 
					suffixMessage+="<QUALSIASI DATA MAGGIORE DELLA DATA DI INIZIO>";
				errors.rejectValue("dateMap[startDate]", "error.date.startDateOfElementAfterStartDateOfItemValidator", [formatter.format(wfItemStartDate.getTime())+suffixMessage], null);					
			}			
			
		

internalOrganizationUnitValidator
validator per controllare presenza di almeno una unità organizzativa NEL FRAGMENT Per maggiori dettagli cfr. excel modello dati dell'entità in questione.

			
			var internalOrganizationUnitWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);
			if(internalOrganizationUnitWfElementSet.isEmpty()){
				errors.reject("error.internalOrganizationUnit.required");
			}
		

contributorValidator
Validator per controllare presenza di almeno un partecipante (contributor)
Dal punto di vista del modello dati si tratta degli attributi contributor
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			
			var contributorWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","contributor", wfService);
			if(contributorWfElementSet.isEmpty()){
				errors.reject("error.contributor.required");
			}
		

keywordErcValidator
validator per controllare presenza di almeno una keywordErc
Dal punto di vista del modello dati si tratta degli attributi keywordErc
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			
			var keywordErcWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","keywordErc", wfService);
			if(keywordErcWfElementSet.isEmpty()){
				errors.reject("error.keywordErc.required");
			}
		

keywordAtecoValidator
validator per controllare presenza di almeno una keywordAteco
Dal punto di vista del modello dati si tratta degli attributi keywordAteco
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			
			var keywordAtecoWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","keywordAteco", wfService);
			if(keywordAtecoWfElementSet.isEmpty()){
				errors.reject("error.keywordAteco.required");
			}
		

keywordUserDefinedValidator
validator per controllare presenza di almeno una keywordUserDefined
Dal punto di vista del modello dati si tratta degli attributi keywordUserDefined
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			
			var keywordUserDefinedWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","keywordUserDefined", wfService);
			if(keywordUserDefinedWfElementSet.isEmpty()){
				errors.reject("error.keywordUserDefined.required");
			}
		

researchLineValidator
validator per controllare presenza di almeno una researchLine
Dal punto di vista del modello dati si tratta degli attributi researchLine
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

			
			var researchLineWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","researchLine", wfService);
			if(researchLineWfElementSet.isEmpty()){
				errors.reject("error.researchLine.required");
			}
		

checkDateExtensionValidator
Questa validazione controlla la coerenza delle date inserite.
Precisamente, viene controllato che:


Per maggiori dettagli cfr. excel modello dati dell'entità in questione.
Questa validazione viene attivata SOLO se ap.checkDateExtensionValidator.enabled=true
	
			var enable=Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.checkDateExtensionValidator.enabled");
			if(enable.equalsIgnoreCase("true")){					   
				var startDate=object.getDateMap().get("startDate");
				var endDate=object.getDateMap().get("endDate");		
				if(startDate ==null){
					errors.reject("error.notNull.fieldLabelKey", [messageUtil.findMessage("label.project.startDate")], null);		
				}
				if(endDate ==null){
					errors.reject("error.notNull.fieldLabelKey", [messageUtil.findMessage("label.project.endDate")], null);			
				}			
				if(endDate != null && startDate != null){
					if(startDate.getTime().after(endDate.getTime())){
						errors.reject("error.date.startDateEndDateNotCompatible");					
					}			
				}
				var durationInMonth=object.getIntegerMap().get("durationInMonth");
				if(durationInMonth==null||durationInMonth<0){
						errors.reject("error.project.durationInMonth");		
				}
			    var wfItemElementSet = object.getWfItemElementSet();			
				if(endDate!=null&&startDate!=null){													
					var extensionSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "extension", wfService);
					var extensionSetIterator=extensionSet.iterator();
					while(extensionSetIterator.hasNext()){
						var extensionElement=extensionSetIterator.next();	
						if (endDate.compareTo(extensionElement.getDateMap().get("currentEndDate"))<0 ||
							durationInMonth<extensionElement.getIntegerMap().get("currentDurationInMonth")){	
							errors.reject("error.project.extension.date");					
						}
						if(extensionElement.getDateMap().get("previousEndDate").getTime().after(extensionElement.getDateMap().get("currentEndDate").getTime())){
							errors.reject("error.date.startDateEndDateNotCompatible");					
						}							
					}
					
					approvalSet= Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "approval", wfService);
					var approvalSetIterator=approvalSet.iterator();
					while(approvalSetIterator.hasNext()){
						var approvalElement=approvalSetIterator.next();	
						var approvalDate=approvalElement.getDateMap().get("approvalDate");
						if (approvalDate!=null){
							if(approvalDate.getTime().after(startDate.getTime())){
							  errors.reject("error.project.approval.date");
							}
						}					
					}					
				};
			}	
		

ownerPositionStartValidator
Validator per controllare che l'owner inserito in start abbia una posizione di ricerca su un dipartimento a partire dalla data di inizio (startDate).
Per maggiori dettagli cfr. excel modello dati dell'entità in questione.
Questa validazione viene attivata SOLO se ap.checkDateExtensionValidator.enabled=true

			function showOrHiddenError(error, mandatory){
				if(mandatory){				
					errors.reject(error);
				}else {			
					log.error(error);					
				}	
			}			
			function showOrHiddenValueError(value,error, mandatory){
				if(mandatory){				
					errors.rejectValue(value,error);
				}else {			
					log.error(error);					
				}	
			}
			if (object.getId()==null){
				var mandatory=Packages.it.cilea.wf.util.WfUtil.getMandatory(object,"owner");							
				if (object.getPersonMap().get("owner")==null)
					showOrHiddenValueError("personMap[owner]","error.owner.required", mandatory);					
				else{
					var typeForConfig = wfService.getWfItemType(wfItem.getWfItemTypeId());
					if (!typeForConfig.getParentWfItemTypeSet().isEmpty()) {
						var parentSetIterator = typeForConfig.getParentWfItemTypeSet().iterator();
						while (parentSetIterator.hasNext()){
							typeForConfig = parentSetIterator.next();
							if (!typeForConfig.getParentWfItemTypeSet().isEmpty()) {
								var parentParentSetIterator = typeForConfig.getParentWfItemTypeSet().iterator();
								while (parentParentSetIterator.hasNext()){
									typeForConfig = parentParentSetIterator.next();
									break;
								}
							}
							break;
						}
					}
				
					var dateDiscriminator = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap." + typeForConfig.getIdentifier().toLowerCase() + ".ownerPositionStartValidator.dateMap.discriminator");
					if(dateDiscriminator == null){
						dateDiscriminator = 'startDate';
					}
					if(object.getDateMap().get(dateDiscriminator)==null)
						showOrHiddenValueError("dateMap["+ dateDiscriminator +"]","error."+dateDiscriminator+".required", mandatory);						
					else{
					
						var owner= object.getPersonMap().get("owner");		
						var ownerPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
						ownerPositionSearch.setPersonId(owner.getId());
						ownerPositionSearch.setDate(object.getDateMap().get(dateDiscriminator).getTime());
						ownerPositionSearch.setOrganizationUnitTypeDescription("department");
						ownerPositionSearch.setDiscriminator("research");
						var ownerPositionSet = gaService.getPositionSearchList(ownerPositionSearch, 0);
							
						if(ownerPositionSet.isEmpty()){
							showOrHiddenError("error.owner.emptyResearchPosition",mandatory);							
						}
					}	
				}
			}
		

multipleOwnerPositionConsistencyStartDateValidator
Validator per controllare che ogni owner inserito abbia un'afferenza valida nella data designata è possibile attivare/disattivare questo controllo con la variabile di configurazione usata anche in ownerPositionStartValidator
SE l'oggetto è già stato creato
SE la variabile è attivata
SE esiste almeno un owner
SE esiste una data di inizio
SE qualcuno non ha una posizione nella data di inizio specificata viene scatenato l'errore: "E' stato trovato uno o più Responsabili scientifici senza una posizione di ricerca su un dipartimento nella data di inizio specificata."
Per maggiori dettagli cfr. excel modello dati dell'entità in questione.
Questa validazione viene attivata SOLO se ap.checkDateExtensionValidator.enabled=true

			//innanzitutto controllo che non sia un oggetto appena creato
			if (object.getId()!=null){
			
				//poi controllo che non ci siano stati errori, se non ce ne sono stati allora vado avanti
				//controllo io se le info che mi servono ci sono o meno
				//if(!errors.hasErrors()){
				
					//poi ricavo se la variabile di configurazione per il controllo è attiva o meno
					//se lo è, allora scateno la validazione
					var mandatory=Packages.it.cilea.wf.util.WfUtil.getMandatory(object,"owner");
					if(mandatory){
					
						//poi controllo che il fragment degli owner non sia vuoto
						var ownerWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement","owner", wfService);
						if(!ownerWfElementSet.isEmpty()){
						
							//poi controllo che vi sia la data di inizio
							var startDate=object.getDateMap().get("startDate");
							//log.error("startDate: "+startDate.getTime());
							if(startDate!=null){
							
								//a questo punto ho tutte le informazioni che mi servono per la validazione
								//vado a ciclare il set degli owner alla ricerca di qualcuno che non abbia una posizione nella data di inizio specificata
								//se ne trovo anche solo uno scateno il messaggio di errore
								
								var ownerSetIterator = ownerWfElementSet.iterator();
								while (ownerSetIterator.hasNext()){
									var ownerElement = ownerSetIterator.next();	//ricavo il singolo element
									var ownerPerson= ownerElement.getPersonMap().get("ownerId");	//ricavo l'owner
									
									//setto il positionSearch in modo da trovare se ho delle position di ricerca per quella data
									var ownerPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
									//log.error("owner id: "+ownerPerson.getId());
									ownerPositionSearch.setPersonId(ownerPerson.getId());
									ownerPositionSearch.setDate(startDate.getTime());
									ownerPositionSearch.setOrganizationUnitTypeDescription("department");
									ownerPositionSearch.setDiscriminator("research");
									var ownerPositionSet = gaService.getPositionSearchList(ownerPositionSearch, 0);
										
									if(ownerPositionSet.isEmpty()){
										errors.reject("error.multipleOwner.emptyResearchPosition");
									}
								}//fine ciclo tra gli owner
								
							}else{
								errors.reject("error.startDate.required");
							}
						}else{
							errors.reject("error.owner.required");
						}
					}
				//}//controllo errori
			}
		

getYearFromStartDateValidator
validator di save che ricava l'anno dalla data di inizio creato perchè gli elementi di input disabilitati della form non vengono salvati

			var startDate=object.getDateMap().get("startDate");
			//log.error("startDate: "+startDate.getTime());
			if(startDate!=null){
				object.year=startDate.get(startDate.YEAR);
			}else{
				errors.reject("error.startDate.required");
			}
		

addOrgUnitFromNewOwnerValidator
Logica che ogni volta che viene aggiunto un nuovo owner, ne ricava il dipartimento e lo aggiunge ai Dipartimenti di afferenza del publicEngagement, se non già presente, altrimenti lancia un errore.
è una logica che viene triggerata in fase di SAVE per l'onwer di Pubblic Engagement (Terza Missione).

			function showOrHiddenError(error, mandatory){
				if(mandatory){				
					errors.reject(error);
				}else {			
					log.error(error);					
				}	
			}
			//script per aggiunta nuovo dipartimento nuovo owner
			//prima controllo che non ci siano stati errori
			//se non ci sono stati allora vado avanti
			if(!errors.hasErrors()){
				
				//inutile, ma mi serve per ricordarmi il contesto
				var wfItemElement=object;							
				var wfItem= wfService.getWfItem(wfItemElement.getWfItemId()); 
				var fragmentInfo=Packages.it.cilea.core.fragment.util.FragmentUtil.getFragmentableInfo(wfItemElement);
				var newOwnerToAdd= wfItemElement.getPersonMap().get(fragmentInfo.getDiscriminator()+"Id");
				
				if(newOwnerToAdd != null){
					var person= gaService.getPerson(newOwnerToAdd.getPersonId());
					var mandatory=Packages.it.cilea.wf.util.WfUtil.getMandatory(wfItem,fragmentInfo.getDiscriminator());
					if(wfItem.getDateMap().get("startDate")==null)
						showOrHiddenError("error.startDate.required",mandatory);
					else{					
						//ricerca del dipartimento associato alla persona
						var ownerDepartmentPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
						ownerDepartmentPositionSearch.setPersonId(person.getId());
						ownerDepartmentPositionSearch.setDate(wfItem.getDateMap().get("startDate").getTime());
						ownerDepartmentPositionSearch.setOrganizationUnitTypeDescription("department");
						ownerDepartmentPositionSearch.setDiscriminator("research");
						var ownerDepartmentPositionSet = gaService.getPositionSearchList(ownerDepartmentPositionSearch, 0);
						
						if(ownerDepartmentPositionSet.isEmpty()){
							showOrHiddenError("error.owner.emptyResearchPosition",mandatory);
	
						}else{
						
							var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(ownerDepartmentPositionSet, "research", "department");
						
							//ciclo posittion in cerca del dipartimento del nuovo owner
							var newOwnerOrgUnit= null;
							var ownerDepartmentPositionSetIterator=ownerDepartmentPositionSet.iterator();							
							while (ownerDepartmentPositionSetIterator.hasNext()){
								var position=ownerDepartmentPositionSetIterator.next();
								if (maxPriority == null || maxPriority.equals(position.getPriority())) {
									newOwnerOrgUnit=position.getOrganizationUnit();
								}
							}
							
							//cerco se c'è già il dipartimento, se no lo aggiungo
							var orgUnitWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);
							var orgUnitWfElementSetIterator=orgUnitWfElementSet.iterator();
							var alreadyAdded=false;
							while(orgUnitWfElementSetIterator.hasNext()){
								var orgUnitElement=orgUnitWfElementSetIterator.next();
								var orgUnit= orgUnitElement.getOrganizationUnitMap().get("ouId");
								if(orgUnit.getOrganizationUnitId()==newOwnerOrgUnit.getOrganizationUnitId()){
									alreadyAdded=true;
								}
							}
							
							if(!alreadyAdded){
								var ouIe=new Packages.it.cilea.wf.model.WfItemElement();
								ouIe.setDiscriminator("internalOrganizationUnit");
								ouIe.setWfItemId(wfItem.getId());
								ouIe.getOrganizationUnitMap().put("ouId", newOwnerOrgUnit);
								var roleId=wfItemElement.getWfDictionaryMap().get("roleId");
								if (roleId!=null&&fragmentInfo!=null){
									Packages.it.cilea.wf.util.WfUtil.addRoleInElementIfPresent(wfItem,roleId,fragmentInfo, ouIe, wfService);
								}					
								Packages.it.cilea.core.fragment.util.FragmentUtil.addNewFragment(ouIe, wfService);				
							}
						}
					}
					
					
				}
				
				
			}
		

notEmptyResearchPositionValidatorTutor

			
			//validator che controlla se il tutor inserito abbia una posizione di ricerca presso un dipartimento
			
			function showOrHiddenError(error, mandatory){
				if(mandatory){				
					errors.reject(error);
				}else {			
					//log.error(error);					
				}	
			}
			
			//prima controllo che non ci siano stati errori
			//se non ci sono stati allora vado avanti
			if(!errors.hasErrors()){
				
				//inutile, ma mi serve per ricordarmi il contesto
				var wfItemElement=object;							
				
				var fragmentInfo=Packages.it.cilea.core.fragment.util.FragmentUtil.getFragmentableInfo(wfItemElement);
				
				//var newTutorToAdd= wfItemElement.getPersonMap().get(fragmentInfo.getDiscriminator()+"Id");	//no così visto che ha discriminator particolare
				var newTutorToAdd= wfItemElement.getPersonMap().get("contributorId");
				var person= gaService.getPerson(newTutorToAdd.getPersonId());
				
				var wfItem= wfService.getWfItem(wfItemElement.getWfItemId());
				var mandatory=Packages.it.cilea.wf.util.WfUtil.getMandatory(wfItem,fragmentInfo.getDiscriminator());
				
				if(wfItemElement.getDateMap().get("startDate")==null)
					errors.reject("error.startDate.required");
				else{					
					//ricerca del dipartimento associato alla persona
					var tutorDepartmentPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
					tutorDepartmentPositionSearch.setPersonId(person.getId());
					tutorDepartmentPositionSearch.setDate(wfItemElement.getDateMap().get("startDate").getTime());
					tutorDepartmentPositionSearch.setOrganizationUnitTypeDescription("department");
					tutorDepartmentPositionSearch.setDiscriminator("research");
					var tutorDepartmentPositionSet = gaService.getPositionSearchList(tutorDepartmentPositionSearch, 0);
					
					if(tutorDepartmentPositionSet.isEmpty()){
						showOrHiddenError("error.tutor.emptyResearchPosition",mandatory);
					}
				}
			}
		

deleteOrgUnitFromOldOwnerValidator

			//script per eliminazione dipartimento vecchio owner
			
			function getDepartmentFromPerson(wfItem, person){
				//ricerca del dipartimento associato alla persona
				var personDepartmentPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
				personDepartmentPositionSearch.setPersonId(person.getId());
				personDepartmentPositionSearch.setDate(wfItem.getDateMap().get("startDate").getTime());
				personDepartmentPositionSearch.setOrganizationUnitTypeDescription("department");
				personDepartmentPositionSearch.setDiscriminator("research");
				var personDepartmentPositionSet = gaService.getPositionSearchList(personDepartmentPositionSearch, 0);
				var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(personDepartmentPositionSet, "research", "department");
				
				//ciclo posittion in cerca del dipartimento della person
				var personDepartmentPositionSetIterator=personDepartmentPositionSet.iterator();							
				while (personDepartmentPositionSetIterator.hasNext()){
					var position=personDepartmentPositionSetIterator.next();
					if (maxPriority == null || maxPriority.equals(position.getPriority())) {
						return position.getOrganizationUnit();
					}
				}
			}
			
			//prima controllo che non ci siano stati errori
			//se non ci sono stati allora vado avanti
			if(!errors.hasErrors()){
				
				//inutile, ma mi serve per ricordarmi il contesto
				var wfItemElement=object;
				var wfItem= wfService.getWfItem(wfItemElement.getWfItemId()); 
				
				var oldOwnerToDelete= wfItemElement.getPersonMap().get("ownerId");
				var person= gaService.getPerson(oldOwnerToDelete.getPersonId());
				//ricavo il dipartimento della persona
				var oldOwnerOrgUnit= getDepartmentFromPerson(wfItem, person);
				
				//cerco tra gli owner se c'è già qualcuno associato allo stesso dipartimento
				var ownerWfElementSet=Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","owner", wfService);
				var ownerWfElementSetIterator=ownerWfElementSet.iterator();
				
				//mi serve per verificare se altri owner hanno il dipartimento in comune
				//se ne trovo un altro con lo stesso dipartimento, incremento
				var ownersWithCommonDepartment=0;
				
				while(ownerWfElementSetIterator.hasNext()){
					var ownerElement=ownerWfElementSetIterator.next();
					var owner=ownerElement.getPersonMap().get("ownerId");
					//per non contare  anche l'owner che sto togliendo
					if(owner.getId()!=person.getId()){
						var ownerOrgUnit=getDepartmentFromPerson(wfItem, owner);
						if(ownerOrgUnit.getOrganizationUnitId()==oldOwnerOrgUnit.getOrganizationUnitId()){
							ownersWithCommonDepartment++;
						}
					}
				}
				
				if(ownersWithCommonDepartment==0){
					var ouIe=null;
					var internalOrganizationUnitSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(wfItem, "it.cilea.wf.model.WfItemElement","internalOrganizationUnit", wfService);
					var internalOrganizationUnitSetIterator=internalOrganizationUnitSet.iterator();
					while(internalOrganizationUnitSetIterator.hasNext()){
						var orgUnitElement=internalOrganizationUnitSetIterator.next();
						var orgUnit= orgUnitElement.getOrganizationUnitMap().get("ouId");
						if(orgUnit.getOrganizationUnitId()==oldOwnerOrgUnit.getOrganizationUnitId()){
							ouIe=orgUnitElement;
						}
					}
					Packages.it.cilea.core.fragment.util.FragmentUtil.deleteFragment(ouIe, wfService);
				}
			}
		

ownerWithSameDepartmentAsHeadValidator
Questa validazione viene triggerata in fase di creazione di un nuovo oggetto in visione dipartimentale.
Verifica che l'utente che sta creando un nuovo oggetto a livello dipartimentale, specifichi come responsabile scientifico una persona che afferisce al proprio dipartimento (alla data di inizio specificata per l'oggetto creato).
La variabile di configurazione ap.<tipologia>.ownerWithSameDepartmentAsHeadValidator.dateMap.discriminator contiene il nome dell'attributo da usare per recuperare la data di inizio relativa all'oggetto creato.
Questa validazione prende in considerazione anche la variabile di configurazione ap.<tipologia>.owner.internalOrganizationUnit.mandatory che specifica se il responsabile scientifico debba obbligatoriamente avere un'afferenza su un dipartimento.

			//validator per headofdepartment
			//prima controllo che non ci siano stati errori		
			if(!errors.hasErrors()){				
				var list=gaAuthorizationService.getAuthoritiesInfoSelectableDisplayList("/DEPARTMENT/ap.profile");
				//controllo per verificare se sono in visione dipartimentale o no
				
				if(list.get(0).getIdentifyingValue()!=-1){
					if (object.getId()==null){			
						//gli altri controlli non li faccio, ci pensano gli altri validator
						
						var owner= object.getPersonMap().get("owner");		
						var ownerPositionSearch = new Packages.it.cilea.ga.command.PositionSearchCommand();
						ownerPositionSearch.setPersonId(owner.getId());
						
						var typeForConfig = wfService.getWfItemType(object.getWfItemTypeId());
						if (!typeForConfig.getParentWfItemTypeSet().isEmpty()) {
							var parentSetIterator = typeForConfig.getParentWfItemTypeSet().iterator();
							while (parentSetIterator.hasNext()){
								typeForConfig = parentSetIterator.next();
								if (!typeForConfig.getParentWfItemTypeSet().isEmpty()) {
									var parentParentSetIterator = typeForConfig.getParentWfItemTypeSet().iterator();
									while (parentParentSetIterator.hasNext()){
										typeForConfig = parentParentSetIterator.next();
										break;
									}
								}
								break;
							}
						}
					
						var dateDiscriminator = Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap." + typeForConfig.getIdentifier().toLowerCase() + ".ownerWithSameDepartmentAsHeadValidator.dateMap.discriminator");
						if(dateDiscriminator == null){
							dateDiscriminator = 'startDate';
						}						
						
						ownerPositionSearch.setDate(object.getDateMap().get(dateDiscriminator).getTime());
						ownerPositionSearch.setOrganizationUnitTypeDescription("department");
						ownerPositionSearch.setDiscriminator("research");
						var ownerPositionSet = gaService.getPositionSearchList(ownerPositionSearch, 0);
						var maxPriority = Packages.it.cilea.ga.util.GaUtil.getMaxPriority(ownerPositionSet, "research", "department");						
						var mandatory=Packages.it.cilea.wf.util.WfUtil.getMandatory(object,"owner");							
						if(mandatory){
							//ciclo posittion in cerca del dipartimento della person
							var department=null;
							var ownerPositionSetIterator=ownerPositionSet.iterator();							
							while (ownerPositionSetIterator.hasNext()){
								var position=ownerPositionSetIterator.next();
								if (maxPriority == null || maxPriority.equals(position.getPriority())) {
									department=position.getOrganizationUnit();
									//log.error("department id: "+department.getOrganizationUnitId());
								}
							}						
							//uso un flag dato che devo ciclare su tutti i possibili dipartimenti
							var flag=false;
							var listIterator=list.iterator();
							if (department!=null){
								while(listIterator.hasNext()){
									var selectable=listIterator.next();
									//log.error("selectable getIdentifyingValue: "+selectable.getIdentifyingValue());							
									if(department.getOrganizationUnitId()==selectable.getIdentifyingValue()){
										flag=true;
									}	
								}
							}						
							if(!flag){
								errors.reject("error.owner.mustBeSameAsHead");
							}
						}
					}
				}
			}
		

departmentChangeRoleValidator
Questa validazione opera sull'elemento internalOrganizationUnit figlio dell'oggetto radice.
Se l'utente è in visione dipartimentale per il dipartimento X e tenta di modificare il ruolo del dipartimento X nell'oggetto radice, viene sollevato un errore se il nuovo ruolo prevede diritti inferiori.
Questa operazione viene impedita in quanto la modifica del ruolo porterebbe l'utente a non potere più operare su quell'oggetto.
Ad esempio se un utente accede in visione dipartimentale ad un progetto e cambia il ruolo del suo dipartimento da "Principale" ad "Aggregato", l'operazione viene impedita perché il ruolo "Aggregato" prevede diritti inferiori.
Questa operazione è consentita in visione completa per i team abilitati.
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

	
			var ouIdToCheck = object.getIntegerMap().get("ouIdPreviousValue");			
			if (ouIdToCheck==null){
				ouIdToCheck=object.getOrganizationUnitMap().get("ouId").getId();
			}	
			
			var ouRoleToCheck = object.getIntegerMap().get("ouRolePreviousValue");			
			var ouRoleDiscriminator="";
			if (ouRoleToCheck==null){
				if (object.getWfDictionaryMap().get("ouRole")!=null){
					ouRoleToCheck=object.getWfDictionaryMap().get("ouRole").getId();
					ouRoleDiscriminator="ouRole";
				} else if (object.getWfDictionaryMap().get("roleId")!=null){
					ouRoleToCheck=object.getWfDictionaryMap().get("roleId").getId();
					ouRoleDiscriminator="roleId";
				}				
			}
					
		    var list=gaAuthorizationService.getAuthoritiesInfoSelectableDisplayList("/DEPARTMENT/ap.profile");
			//controllo per verificare se sono in visione dipartimentale o no
			var listIterator=list.iterator();				
			while(listIterator.hasNext()){
				var selectable=listIterator.next();				
				if(ouIdToCheck==selectable.getIdentifyingValue()){
					object.getOrganizationUnitMap().put("ouId",gaService.getOrganizationUnit(ouIdToCheck));
					object.getWfDictionaryMap().put("ouRole",wfService.getWfDictionary(ouRoleToCheck));
					wfService.saveOrUpdate(object);						 	
					errors.reject("error.operation.headOfDepartment.changeRole");
				}	
			}		
		

departmentDeleteValidator
Questa validazione opera sull'elemento internalOrganizationUnit figlio dell'oggetto radice.
Se l'utente è in visione dipartimentale per il dipartimento X e tenta di eliminare il dipartimento X dall'oggetto radice, viene sollevato un errore in quanto cancellando questa associazione, l'utente non potrebbe più operare su quell'oggetto.
Questa operazione è consentita in visione completa per i team abilitati.
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

	
			// Elenco dei miei dipartimenti 
		    var list=gaAuthorizationService.getAuthoritiesInfoSelectableDisplayList("/DEPARTMENT/ap.profile");
			//controllo per verificare se sono in visione dipartimentale o no
			var listIterator=list.iterator();		
			while(listIterator.hasNext()){
				var selectable=listIterator.next();			
				if(object.getOrganizationUnitMap().get("ouId").getId()==selectable.getIdentifyingValue()){
					errors.reject("error.operation.headOfDepartment.cannotDeleteHisDepartment");
				}	
			}
		

notEditableFragmentValidator
Questa validazione impedisce la modifica dei dati in un fragment.
Può agire sia in caso di salvataggio che in caso di eliminazione.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(object.getWfItem().getBooleanMap().get("legacy"))){		
				errors.reject("error.operation.notallowed");
			}
		

contributorAndOwnerValidatorWithStartEndDate
Questa validazione opera sugli elementi owner (responsabile scientifico) e contributor (partecipante) figli dell'oggetto radice.
Viene verificato che l'intervallo di validità degli oggetti figli siano compresi all'interno della validità dell'oggetto padre.
Gli attributi per le date di inizio e fine sono startDate e endDate sia per gli elementi owner e contributor che per l'oggetto padre.
Per maggiori dettagli cfr. excel modello dati dell'entità in questione.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){						
				var elementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "contributor", wfService);
				elementSet.addAll(Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService));
				if (elementSet.size()>0){
					var elementSetIterator = elementSet.iterator();				
					var wfItemStartDate = object.getDateMap().get("startDate");
					var wfItemEndDate = object.getDateMap().get("endDate");
					var formatter = Packages.org.apache.commons.lang.time.FastDateFormat.getInstance("dd/MM/yyyy");
					var elementWithWrongInterval=[];
								
					while (elementSetIterator.hasNext()){										
						var element = elementSetIterator.next();												
						var wfItemElementStartDate = element.getDateMap().get("startDate");
						
						if( wfItemElementStartDate != null && wfItemStartDate && (wfItemElementStartDate.before(wfItemStartDate) || (wfItemEndDate!=null && wfItemElementStartDate.after(wfItemEndDate)))  ){
							var discriminator = element.getDiscriminator();
							if(element.getDiscriminator().contains(".")){
							 	discriminator = element.getDiscriminator().substring(0, element.getDiscriminator().indexOf("."))
							}
							elementWithWrongInterval.push(element.getPersonMap().get(discriminator + "Id").getDisplayValue());
						}								
					}
					
					if (elementWithWrongInterval.length>0){
						errors.reject("error.contributorAndOwner.wrongInterval", [elementWithWrongInterval.toString()], "error.contributorAndOwner.wrongInterval");
					}			
				}				
			}
		

contributorAndOwnerStartDateValidator
Questa validazione opera sugli elementi owner (responsabile scientifico) e contributor (partecipante) figli dell'oggetto radice.
Viene verificato che per ogni owner e contributor, sia specificata la data di inizio validità (attributo startDate)
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){						
				var elementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "contributor", wfService);
				elementSet.addAll(Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService));
				if (elementSet.size()>0){
					var elementSetIterator = elementSet.iterator();				
					var elementToEdit = [];
								
					while (elementSetIterator.hasNext()){										
						var element = elementSetIterator.next();												
						var wfItemElementStartDate = element.getDateMap().get("startDate");
						
						if(wfItemElementStartDate == null && !wfItemElementStartDate){
							var discriminator = element.getDiscriminator();
							if(element.getDiscriminator().contains(".")){
							 	discriminator = element.getDiscriminator().substring(0, element.getDiscriminator().indexOf("."))
							}
							elementToEdit.push(element.getPersonMap().get(discriminator + "Id").getDisplayValue());
						}								
					}
					
					if (elementToEdit.length > 0){
						errors.reject("error.contributorAndOwner.startDate.required", [elementToEdit.toString()], "error.contributorAndOwner.startDate.required");
					}			
				}				
			}
		

ownerRoleValidator
Questa validazione opera sugli elementi owner (responsabile scientifico) e contributor (partecipante) figli dell'oggetto radice.
Viene verificato che per ogni owner e contributor, sia specificata la data di inizio validità (attributo startDate)
Per maggiori dettagli cfr. excel modello dati dell'entità in questione

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				if (Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.prj.owner.role.enabled").equalsIgnoreCase("true")){
					var elementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "getWfItemElementSet", "it.cilea.wf.model.WfItemElement", "owner", wfService);
					if (elementSet.size()>0){
						var elementSetIterator = elementSet.iterator();				
						var elementToEdit = [];
									
						while (elementSetIterator.hasNext()){										
							var element = elementSetIterator.next();												
							var wfItemElementRoleId = element.getWfDictionaryMap().get("roleId");
							
							if(wfItemElementRoleId == null && !wfItemElementRoleId){
								var discriminator = element.getDiscriminator();
								if(element.getDiscriminator().contains(".")){
								 	discriminator = element.getDiscriminator().substring(0, element.getDiscriminator().indexOf("."))
								}
								elementToEdit.push(element.getPersonMap().get("ownerId").getDisplayValue());
							}								
						}
						
						if (elementToEdit.length > 0){
							errors.reject("error.owner.role.required", [elementToEdit.toString()], "error.owner.role.required");
						}			
					}			
				}				
			}
		

notEditableByDepartmentValidator
Questa validazione controlla che l'utente corrente NON appartenga al team "Direttori di dipartimento cui negare accesso in modifica ai Progetti/Contratti".
Questo è un team con agganciata la funzione "Risorsa per Direttori di dipartimento cui negare accesso in modifica ai Progetti/Contratti" (/ap/department/onlyRead.function)

La visione dipartimentale consente a chiunque appartenga ai team "Profilo di dipartimento per XXX" di accedere con i diritti dipartimentali al flusso.
In questo team sono presenti sia i direttori di dipartimento che i referenti amministrativi.
Questa validazione consente l'accesso in scrittura ai soli referenti amministrativi.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				var gaUserDetail = Packages.it.cilea.ga.authorization.context.GaAuthorizationUserHolder.getUser();	
				var userId = gaUserDetail.getUserId();
				
				var searchCommand = new Packages.it.cilea.ga.command.TeamUserLinkSearchCommand();
				searchCommand.setUserId(userId);
				var linkList = gaService.getTeamUserLinkSearchList(searchCommand, 0);
				var listIterator = linkList.iterator();				
				while(listIterator.hasNext()){
					var teamUserLink = listIterator.next();		
					if(teamUserLink.getTeamId() == Packages.it.cilea.core.configuration.util.ConfigurationUtil.getConfigValue("ap.department.onlyRead.team")){
						errors.reject("error.operation.notallowed");
						break;
					}
				}	
			}
		

notCreatableByDepartmentValidator
Questa validazione controlla che l'utente corrente NON appartenga al team "Direttori di dipartimento cui negare accesso in creazione ai Progetti/Contratti".
Questo è un team con agganciata la funzione "Risorsa per Direttori di dipartimento cui negare accesso in modifica ai Progetti/Contratti" (/ap/department/onlyRead.function)

La visione dipartimentale consente a chiunque appartenga ai team "Profilo di dipartimento per XXX" di accedere con i diritti dipartimentali al flusso.
In questo team sono presenti sia i direttori di dipartimento che i referenti amministrativi.
Questa validazione consente l'accesso in scrittura ai soli referenti amministrativi.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				var gaUserDetail = Packages.it.cilea.ga.authorization.context.GaAuthorizationUserHolder.getUser();	
				var authority = gaUserDetail.getCurrentAuthorityIdentifier();
				if(authority == "ROLE_DEPARTMENT"){
					var validateLogic = Packages.it.cilea.wf.WfConstant.VALIDATE_LOGIC_MAP.get("notEditableByDepartmentValidator");
					validateLogic.validate(request, object, errors);
				}
			}
		

personInFragmentValidator
Questa validazione controlla che all'interno delle tabelle dei Soggetti Interni NON ci siano nominativi duplicati.

	
			if (!Packages.java.lang.Boolean.TRUE.equals(wfItem.getBooleanMap().get("legacy"))){		
				var personMap = new Packages.java.util.HashMap();
				var discriminator = ["owner", "contributor"];
				var dataDiscriminator = ["ownerId", "contributorId"];
				var discriminatorLen = discriminator.length;
				var duplucateList = new Packages.java.util.ArrayList();
				for (i = 0; i < discriminatorLen; i++) {
					var elementSet = Packages.it.cilea.core.fragment.util.FragmentUtil.getCurrentFragmentSetByParentAndDiscriminator(object, "it.cilea.wf.model.WfItemElement",discriminator[i], wfService);
					var elementSetIterator = elementSet.iterator();
					while(elementSetIterator.hasNext()){
						var element = elementSetIterator.next();
						var personId = element.getPersonMap().get(dataDiscriminator[i]).getId();
						if(personMap.get(personId) != null){
							duplucateList.add(gaService.getPerson(personId).getDescription());
						} else {
							personMap.put(personId,"1");
						}
					}
				}
				if(duplucateList.size() > 0){
					errors.reject("error.contributorAndOwner.duplicate", [duplucateList.toString()], "error.contributorAndOwner.duplicate");
				}
			}
		

wfActionLogicSaveDisplayAsDefault

it.cilea.wf.logic.action.save.WfActionLogicSaveDisplayAsDefault

wfActionLogicSaveYearFromStartDate

it.cilea.wf.logic.action.save.WfActionLogicSaveYearFromStartDate

notAllowedValidator
Questa logica scatena un errore e blocca l'azione sulla quale è collegata. Per esempio se collegata in delete ad un element in un task dell'onwer, impedisce all'owner di concellare l'element.

			
			errors.reject("error.operation.notallowed");				
		

ownerCannotEditHimself
Questa validazione viene scatenata in fase di modifica di un elemento.
Controlla che l'utente corrente non sia un Responsabile scientifico che stia cercando di togliersi la responsabilità, andando a sostituire qualcun'altro al suo posto.
Questa validazione è data dal fatto che l'owner deve comunque poter modificare e/o aggiungere altri Responsabili scientifici, motivo per cui il semplice notAllowedValidator non può essere applicato.
Per poter utilizzare questa validazione è necessario aggiungere alla form l'attributo ownerIdPreviousValue, che contiene l'id della persona precedente.

			//log.error("--ownerCannotEditHimself--");
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement = object;
			
			//controllo se è un nuovo element o meno
			//se è un nuovo element allora non avrà la persona settata
			if(wfItemElement.getId() != null){
			
				//prima ricavo la persona precedente a quella che sto aggiungendo
				var previousOwnerId = wfItemElement.getIntegerMap().get("ownerIdPreviousValue");
				//ulteriore controllo per controllare che la persona precedente ci sia non è utile (?)
				
				//successivamente vado a ricavare la persona che sta editando in questo momento
				var personalUserName = request.getUserPrincipal().getName();
				var personId = gaService.getUser(personalUserName).getPersonId();
				
				//se le due persone coincidono, vuol dire che sto provando ad editarmi
				if(previousOwnerId == personId){
				
					//adesso ricavo la persona che sto mettendo in questo momento
					//se non sono io vuol dire che sto cercando di sostituirmi
					var ownerId = wfItemElement.getPersonMap().get("ownerId").getPersonId();
					
					if(ownerId != previousOwnerId){
					
						//allora vado a re-sostituire con me stesso e salvo
						var person = gaService.getPerson(previousOwnerId);
						wfItemElement.getPersonMap().put("ownerId", person);
						wfService.saveOrUpdate(wfItemElement);
						
						errors.reject("error.operation.ownerCannotEditHimself");
					}
				}
			}
		

ownerCannotDeleteHimself
Questa validazione viene scatenata in fase di eliminazione di un elemento.
Controlla che l'utente corrente non sia un Responsabile scientifico che stia cercando di togliersi la responsabilità, andando ad eliminare se stesso dalla lista.
Questa validazione è data dal fatto che l'owner deve comunque poter eliminare altri Responsabili scientifici, motivo per cui il semplice notAllowedValidator non può essere applicato.

			//log.error("--ownerCannotDeleteHimself--");
			//inutile, ma mi serve per ricordarmi il contesto
			var wfItemElement = object;
			
			//prima ricavo la persona che sto eliminando
			var ownerId = wfItemElement.getPersonMap().get("ownerId").getPersonId();
			
			//successivamente vado a ricavare la persona che sta editando in questo momento
			var personalUserName = request.getUserPrincipal().getName();
			var personId = gaService.getUser(personalUserName).getPersonId();
			
			//se le due persone coincidono, vuol dire che sto provando ad eliminarmi
			if(ownerId == personId)	
				errors.reject("error.operation.ownerCannotDeleteHimself");
			
		

checkCreationPermissionsValidator
Questa validazione viene scatenata in fase di creazione dell'oggetto.
Controlla che l'utente corrente abbia i permessi per creare la tipologia di oggetto in questione.
Agli utenti viene presentata sempre la lista dei tipi di oggetto che possono creare.
Questa validazione, comunque, serve per prevenire eventuali "hacking" di utenti che modificano volutamente il markup del form inserendo un tipo di oggetto per il quale non hanno le autorizzazioni.

			//da controllare solo in fase di prima creazione
			if (wfItem.getId()==null){
				var isCreateAllowed=Packages.it.cilea.wf.util.WfUtil.isWfItemTypeAllowedForCurrentUser(wfItem.getWfItemTypeId(), applicationContext);
				if (!isCreateAllowed){
					errors.reject("error.ap.wfItemType.creationNotAllowed");					
				}
			}				
		

sameDefinitionForGenericItemValidator
Questa validazione viene scatenata in fase di cambio di Tipo dell'oggetto.
Validatore che controlla che se si cambia tipo di flusso, questo nuovo tipo sia compatibile (same definition number) in modo che un tipo di progetto rimanga un tipo di progetto.

	
			//estraggo il wfItemId
			//log.error("entro nel validator sameDefinitionForGenericProjectValidator");
			var myNEWWfItemType = object.getWfItemTypeId();
			var myOLDWfItemType = object.getIntegerMap().get("wfItemTypeIdPreviousValue");
			if (myOLDWfItemType==null)
				throw "To use sameDefinitionForGenericItemValidator you MUST specify wfItemTypeIdPreviousValue hidden value";
			//log.error("dovrebbe essere il mio definition new:" + myNEWWfItemType + " old: " + myOLDWfItemType);
			
			//con il wfItemID tiro fuori tramite il wfservice la definition
			var newItemType=wfService.getWfItemType(myNEWWfItemType);
			var oldItemType=wfService.getWfItemType(myOLDWfItemType);
			//log.error("newItemType:"+newItemType+" oldItemType:"+oldItemType);
			
			//confronto le due definition se sono diverse vuol dire che il cambio di flusso non è compatibile
			if(!newItemType.getWfDefaultDefinitionId().equals(oldItemType.getWfDefaultDefinitionId())){
				object.setWfItemTypeId(myOLDWfItemType);
				errors.reject("error.ap.definitionError");
			}
		

changeItemTypeForNotSynchronizedItemValidator
Questa validazione viene scatenata in fase di cambio di Tipo dell'oggetto.
Non è possibile cambiare la tipologia, la scheda è già stata sincronizzata con U-GOV o l'utente non possiede i permessi sulla nuova tipologia selezionata.

	
			//estraggo il wfItemId
			
			var myNEWWfItemType = object.getWfItemTypeId();
			var myOLDWfItemType = object.getIntegerMap().get("wfItemTypeIdPreviousValue");
			if (myOLDWfItemType==null)
				throw "To use changeItemTypeValidator you MUST specify wfItemTypeIdPreviousValue hidden value";
			
			//confronto le due tipologie, se sono diverse e ho già sincronizzato vuol dire che il cambio di tipologia non è compatibile
			
			if(myNEWWfItemType != myOLDWfItemType){
				
				if(object.getStringMap().get("ugovIdentifier") != null){
					object.setWfItemTypeId(myOLDWfItemType);
					errors.reject("error.ap.itemTypeError");
				} else {
					var isCreateAllowed=Packages.it.cilea.wf.util.WfUtil.isWfItemTypeAllowedForCurrentUser(myOLDWfItemType, applicationContext);
					if(!Packages.java.lang.Boolean.TRUE.equals(isCreateAllowed)){
						errors.reject("error.ap.itemTypeError");
					}
				}
			
			}
		

changeItemTypeForSynchronizedItemValidator
Questa validazione viene scatenata in fase di cambio di Tipo dell'oggetto in un determinato stato del flusso.
Non è possibile cambiare la tipologia in questo stato del flusso in quanto non compatibile con altri stati di altri flussi.

	
			//estraggo il wfItemId
			
			var myNEWWfItemType = object.getWfItemTypeId();
			var myOLDWfItemType = object.getIntegerMap().get("wfItemTypeIdPreviousValue");
			if (myOLDWfItemType==null)
				throw "To use changeItemTypeValidator you MUST specify wfItemTypeIdPreviousValue hidden value";
			
			if(myNEWWfItemType != myOLDWfItemType){
				object.setWfItemTypeId(myOLDWfItemType);
				errors.reject("error.ap.itemTypeError.step2");
			}
		

itemTypeNotWithdrawnValidator
Questa validazione controlla che in salvataggio non venga inserita una tipologia che è stata eliminata.
Non è possibile cambiare la tipologia in una che non è più valida.
Posso però mantenere un item che è già presente in quella tipologia, se poi però vado a modificarla non posso tornare indietro alla tipologia non valida.

		
			
			var newWfItemTypeId = object.getWfItemTypeId();
			var newWfItemType = wfService.getWfItemType(newWfItemTypeId);
			
			//log.error("wfItemType: " + newWfItemType.getDisplayValue());
			//log.error("getWithdrawn: " + newWfItemType.getWithdrawn());
			
			if(newWfItemType.getWithdrawn() == true){
			
				//ho trovato una tipologia eliminata
				//adesso controllo se prima fosse la stessa, perchè devo mantenere comunque il pregresso
				
				var oldWfItemTypeId = object.getIntegerMap().get("wfItemTypeIdPreviousValue");
				//var oldWfItemType = wfService.getWfItemType(oldWfItemTypeId);
				
				//controllo inoltre che la previousValue sia presente
				if (oldWfItemTypeId == null)
					throw "To use itemTypeNotWithdrawnValidator you MUST specify wfItemTypeIdPreviousValue hidden value";
				
				if(newWfItemTypeId != oldWfItemTypeId){
					errors.reject("error.ap.wfItemType.withdrawn");
				}	
			}	
			
		

wfActionLogicSaveOwnerDependentNewIdentifier

			var myNEWWfItemType = object.getWfItemTypeId();
			var myOLDWfItemType = object.getIntegerMap().get("wfItemTypeIdPreviousValue");
			
			if (myOLDWfItemType==null)
				throw "To use changeItemTypeValidator you MUST specify wfItemTypeIdPreviousValue hidden value";
			
			if(myNEWWfItemType != myOLDWfItemType){
				var startLogic = Packages.it.cilea.wf.WfConstant.START_LOGIC_MAP.get("wfStartLogicOwnerDependentIdentifier");
				startLogic.start(object, request);
				object.getIntegerMap().put("wfItemTypeIdPreviousValue",object.getWfItemTypeId());

			}
		

wfActionLogicSaveStandardNewIdentifier

			var myNEWWfItemType = object.getWfItemTypeId();
			var myOLDWfItemType = object.getIntegerMap().get("wfItemTypeIdPreviousValue");
			if (myOLDWfItemType==null)
				throw "To use changeItemTypeValidator you MUST specify wfItemTypeIdPreviousValue hidden value";
			
			if(myNEWWfItemType != myOLDWfItemType){
				var startLogic = Packages.it.cilea.wf.WfConstant.START_LOGIC_MAP.get("wfStartLogicStandardIdentifier");
				startLogic.start(object, request);
				object.getIntegerMap().put("wfItemTypeIdPreviousValue",object.getWfItemTypeId());
			}
		

wfActionLogicTransitionLogger
Questa logica serve per la gestione del logging delle transizioni di stato.
E' necessario inserirla come enter action logic per tutti gli stati nei flussi che prevedono il logging delle transizioni di stato.
Nel caso in cui sia ritenuto necessario, è possibile richiedere all'utente che sta effettuando la transizione di stato di inserire un messaggio.
Questo messaggio verrà conservato nel log delle transizioni.

La gestione del messaggio opzionale è gestito dall'attributo transitionComment che deve essere configurato come validazione di enter con il validator @Required.

			var formatter=new Packages.java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
			var currentDate="["+formatter.format(new Packages.java.util.Date())+"]";
			var user=Packages.it.cilea.ga.authorization.context.GaAuthorizationUserHolder.getUser();
			
			if (user!=null){
				var message="";
				if(Packages.org.apache.commons.lang.StringUtils.isNotBlank(wfItem.getClobMap().get("transitionsLog"))){
					message+="_______________________________________________________________"+ "

";
				} else {				
					wfItem.getClobMap().put("transitionsLog", "");
				}
				message+=currentDate+" <strong>"+user.getLastName()+" "+user.getFirstName()+"</strong> ("+user.getUsername()+")"+"
";
				message+="Transizione verso "<strong>"+wfItem.getWfState().getDisplayValue()+"</strong>" ("+wfItem.getWfState().getDescription()+")";
				if (Packages.org.apache.commons.lang.StringUtils.isNotBlank(wfItem.getStringMap().get("transitionComment"))){			
					message+="
<strong>Motivazione transizione di stato</strong>
";
					message+="<i>"+wfItem.getStringMap().get("transitionComment")+"</i>";				
				}
				message+="
";			
				wfItem.getClobMap().put("transitionsLog", wfItem.getClobMap().get("transitionsLog")+message);
				wfItem.getStringMap().put("transitionComment", null);
			}
		

wfActionLogicWarningHandler
Questa logica serve per la gestione dei messaggi di warning.
E' necessario inserirla come enter action logic per tutti gli stati di tutti i flussi che prevedono messaggi di warning.
La gestione dei warning è pilotata dall'attributo booleano warningAcknowlegement che deve essere configurato come validazione di enter con il validator @Boolean.TRUE specificando di volta in volta il messaggio di warning da presentare. Per maggiori dettagli cfr. excel modello dati dell'entità Progetto

			wfItem.getBooleanMap().put("warningAcknowlegement", null);
		

isNotLegacy
Questa è un'applicability rule che viene valutata prima di eseguire altre validazioni.
Se ritorna true allora vengono eseguite le altre validazioni altrimenti no.
Questa regola considera l'attributo legacy, tipicamente con etichetta "Disattivazione validazioni" (cfr il modello dati)
Per tutti gli oggetti che hanno questo attributo valorizzato a true vengono disattivate le validazioni e le eventuali sincronizzazioni.

			(
				object.getBooleanMap().get('legacy')==null 
				|| 
				Packages.java.lang.Boolean.FALSE.equals(object.getBooleanMap().get('legacy'))
			)