/*
 * (c) Copyright Trilog Group 2004-2012. All Rights Reserved.
 */

function replaceUserOnProject(oldDN, oldCN, newDN, newCN, siteId, projectId, replaceTasks, replaceIssues, replaceDocuments, replaceChanges, replaceTimeSheets, replaceDefaultWf, replaceDefaultSecurity){
	
	// warning, if we replace a user by himself, the result is buggy (user is not affected anymore to its tasks).
	if (oldDN==newDN) return;
	
	try {
	//set bizdap users to reassign workflow 
	var oldUser = new BizDAPUser();
	oldUser.setName(oldCN);
	oldUser.setDN(oldDN);
	var newUser = new BizDAPUser();
	newUser.setDN(newDN);
	newUser.setName(newCN);
	
	if(replaceTasks){
		var alreadyLocked = false;
		//try to lock all user's tasks (pending and in progress) first
		var scheduleDB=null;
		var view = null;
		var pendingTasksArray = new Array();
		var taskIndex = 0;
		try{
			scheduleDB= session.openDatabase("tg_pe_schedule");
			view = scheduleDB.openView("alltasksbysiteidprojectidandwbssortedid", "status != 'Done' and resourcedn='"+StringUtil.encodeToJavaString(oldDN)+"' and siteid='"+siteId+"' and projectid='"+projectId+"'");
			var docIds = view.getAllDocumentIds();
			for (var i = 0 ; i < docIds.length ;i++) {
				var taskDoc = scheduleDB.getDocumentById(docIds[i]);
				try{
					taskDoc.lock(300);
				}catch(e) {
					alreadyLocked = true;
					break;
				}
				
				pendingTasksArray[taskIndex] = taskDoc;
				taskIndex++;
			}
					
			if (alreadyLocked) {
				//unlock all the ones we locked
				for (var i = 0; i < pendingTasksArray.length; i++) {
					pendingTasksArray[i].unlock();
					pendingTasksArray[i].close();
				}
				return 2; //"Some of the user's tasks were already locked. Please try again later.";					
			}
			
			if (taskIndex>0){
				replaceUserOnTasks(oldDN, newDN, newCN,pendingTasksArray);
				
				// we need to reschedule the project
				var result=com.triloggroup.pe.schedule.ScheduleUtil.runFullReschedule(session,siteId,projectId,false/*isTemplate*/,false/*sendstartDateAlert*/);
				if (result.getErrorCode() != com.triloggroup.pe.schedule.SchedulingResult.SUCCESS){
					if (result.getErrorCode() == com.triloggroup.project.schedule.ScheduleCst.ERROR_LOCKING_SCHEDULE){
						return 2; //"Some of the user's tasks were already locked. Please try again later."
					} else {
						return com.triloggroup.project.schedule.ScheduleCst.UNKNOWN_ERROR;
					}
				}
			}
			
			replaceWBSSupervisorsInWBS(oldDN, newDN, newCN, scheduleDB, siteId, projectId);

		}finally{
			if (view != null)	view.close();
			if (scheduleDB!=null)	scheduleDB.close();
		}
	}
	
	replaceActionUserOnProject(oldUser, newUser,siteId,projectId,replaceIssues,replaceDocuments,replaceChanges,replaceTimeSheets );
	
	if(replaceDefaultSecurity){
		replaceUserInDefaultSecurity(oldDN, newDN,newCN,siteId, projectId);
	}
	if(replaceDefaultWf){
		replaceUserInDefaultWorkflow(oldDN, newDN,newCN,siteId, projectId);
	}
	
	//add user to project if necessary
	var projectUsers = session.getLookupValues("tg_pe_project","allusersbysiteidprojectidanddn",siteId + "|" + projectId ,"userdn");
	if (@IsMember(newDN, projectUsers) == 0) {
		
		// do not add the user if already present in the project
		var oldUserRole = getUserLocalRole(siteId, projectId, oldDN);
		var unregistered = false;
		if(context.getDirectory().getDirectoryUser(newDN, true/*skipgroups*/)==null){
			unregistered = true;
		}
	 	com.triloggroup.pe.administration.AdministrationUtil.createUserDocument(context, newDN,newCN,oldUserRole,
	 		""/*team*/,projectId,false/*isTemplate*/,null/*calendarId*/,null/*msuid*/, unregistered,""/*unregisteredUserEmail*/,siteId);
	}
	
	}catch(e){
		e.printStackTrace();
		return com.triloggroup.project.schedule.ScheduleCst.UNKNOWN_ERROR;
	}
}

function replaceActionUserOnProject(oldUser, newUser,siteId,projectId,replaceIssues,replaceDocuments,replaceChanges,replaceTimeSheets){
	if (replaceIssues){
		replaceActionUserOnIssues(oldUser, newUser,siteId,projectId);
	}
	
	if (replaceDocuments){
		replaceActionUserOnDocuments(oldUser, newUser,siteId,projectId);
	}
	
	if (replaceChanges){
		replaceActionUserOnChanges(oldUser, newUser,siteId,projectId);
	} 
	
	if (replaceTimeSheets){
		replaceActionUserOnTimeSheets(oldUser, newUser,siteId,projectId);
	}
}

function replaceUserOnTasks(oldresourceDN, newresourceDN, newresourceCN,taskArray){
	for (var i=0; i<taskArray.length; i++){
		var taskDoc = taskArray[i];
		//replace user in tasks
		//check if new resource already exists
		var existingResource = taskDoc.getStringValue("/task/user[dn=\""+newresourceDN+"\"]/cn");
		if (existingResource=="" || existingResource ==null){
			taskDoc.setStringValue("/task/user[dn=\""+oldresourceDN+"\"]/cn", newresourceCN);
			taskDoc.setStringValue("/task/user[dn=\""+oldresourceDN+"\"]/dn", newresourceDN);
		}else{
			var usertoBeReplaced = taskDoc.nodes("/task/user[dn=\""+oldresourceDN+"\"]")[0];
			if (usertoBeReplaced!=null){
				usertoBeReplaced.detach();
			}
		}
		taskDoc.save();
	}
	// warning, we need to reschedule the project(s) (must be done by the caller)
}


function replaceActionUserOnIssues(oldUser, newUser,siteId,projectId){
	import pe_workflow;
	var supportDB = null;
	var pendingSupportRequestsView=null;
	
	try{
		supportDB = session.openDatabase("tg_pe_support");
		supportDB.setAdministrationMode(true);		
		var oldDN = oldUser.getDN();
		var pendingSupportRequestsQuery="(FB_ACTIONUSERS='"+StringUtil.encodeToJavaString(oldDN)+"' OR wfapprover='"+StringUtil.encodeToJavaString(oldDN)+"') and siteid='"+siteId+"' and projectid='"+projectId+"'"; 
		pendingSupportRequestsView = supportDB.openView("allrequestsdescbyid",pendingSupportRequestsQuery);
		var docIds = pendingSupportRequestsView.getAllDocumentIds();

		for (var i = 0 ; i < docIds.length; i++) {
			var pendingSupportDocument = supportDB.getDocumentById(docIds[i]);
			var workflowContext = pendingSupportDocument.getWorkflowContext();
			var actionUsers = workflowContext.getActionUsers();
			if (@IsMember(oldDN, actionUsers)) {
				// if action user -> reassign task
				workflowContext.reassignTask(oldUser,newUser,false);
			}
			//if assigned to replace in document
			var assignedToNode = pendingSupportDocument.nodes("/supportrequest/assignedto[dn=\""+oldDN+"\"]")[0];
			if (assignedToNode!=null){
				assignedToNode.setStringValue("cn",newUser.getName());
				assignedToNode.setStringValue("dn",newUser.getDN());
			}
			// always replace in workflow approvers and notification list
			replaceUserInWorkflowMetadata(oldUser, newUser, pendingSupportDocument);
			
			pendingSupportDocument.save();
			pendingSupportDocument.close();	
		}
	}finally{
		if (pendingSupportRequestsView!=null){
			pendingSupportRequestsView.close();
		}
		supportDB.setAdministrationMode(false);
		if(supportDB!=null){
			supportDB.close();
		}
	}
}

function replaceActionUserOnDocuments(oldUser, newUser,siteId,projectId){
	import pe_workflow;
	var docDB  = null;
	var pendingDocumentsView =null;
	try{
		docDB = session.openDatabase("tg_pe_document");
		docDB.setAdministrationMode(true);		
		//pending documents
		var oldDN = oldUser.getDN();
		var pendingDocumentsQuery="(FB_ACTIONUSERS='"+StringUtil.encodeToJavaString(oldDN)+"' OR wfapprover='"+StringUtil.encodeToJavaString(oldDN)+"') and siteid='"+siteId+"' and projectid='"+projectId+"'"; 
		pendingDocumentsView = docDB.openView("allpublicdocumentsbytitle",pendingDocumentsQuery);
		var docIds = pendingDocumentsView.getAllDocumentIds();
		for (var i = 0 ; i < docIds.length ; i++) {
			var pendingDocument = docDB.getDocumentById(docIds[i]);
			var workflowContext = pendingDocument.getWorkflowContext();
			var actionUsers = workflowContext.getActionUsers();
			if (@IsMember(oldDN, actionUsers)) {
				// if action user -> reassign task
				workflowContext.reassignTask(oldUser,newUser,false);
			}
			
			// always replace in workflow approvers and notification list
			replaceUserInWorkflowMetadata(oldUser, newUser, pendingDocument);
			pendingDocument.save();			
			pendingDocument.close();			
		}
	}finally{
		if (pendingDocumentsView!=null){
			pendingDocumentsView.close();
		}
		docDB.setAdministrationMode(false);
		if(docDB!=null){
			docDB.close();
		}
	}
}

function replaceActionUserOnChanges(oldUser, newUser,siteId,projectId){
	import pe_workflow;
	var changeDB  = null;
	var pendingChangesView=null;
	try{			
		changeDB = session.openDatabase("tg_pe_change");
		changeDB.setAdministrationMode(true);
		var oldDN = oldUser.getDN();
		var pendingChangesQuery="(FB_ACTIONUSERS='"+StringUtil.encodeToJavaString(oldDN)+"' OR wfapprover='"+StringUtil.encodeToJavaString(oldDN)+"') and siteid='"+siteId+"' and projectid='"+projectId+"'";
		pendingChangesView = changeDB.openView("allchangerequests",pendingChangesQuery);
		var docIds = pendingChangesView.getAllDocumentIds();
		
		for (var i = 0 ; i < docIds.length; i++) {	
			var pendingChangeDocument = changeDB.getDocumentById(docIds[i]);
			var workflowContext = pendingChangeDocument.getWorkflowContext();
			var actionUsers = workflowContext.getActionUsers();
			if (@IsMember(oldDN, actionUsers)) {
				// if action user -> reassign task
				workflowContext.reassignTask(oldUser,newUser,false);
			}
			// always replace in workflow approvers and notification list
			replaceUserInWorkflowMetadata(oldUser, newUser, pendingChangeDocument);
			pendingChangeDocument.save();
			pendingChangeDocument.close();
		}
		
	}finally{
		if (pendingChangesView!=null){
			pendingChangesView.close();
		}
		changeDB.setAdministrationMode(false);
		if(changeDB!=null){
			changeDB.close();
		}
	}
}

function replaceUserInWorkflowMetadata(oldUser, newUser, document) {
	var oldDn = oldUser.getDN();
	var newDn = newUser.getDN();
	var newCn = newUser.getName();
	
	var rootElement = document.getRootElement();
	var approverNodes = rootElement.nodes("metadata/workflow/step/approver[dn='"+oldDn+"']");
	for (var i = 0 ; i < approverNodes.length; i++) {
		approverNodes[i].setStringValue("dn", newDn);
		approverNodes[i].setStringValue("cn", newCn);
	}
	
	var notificationNodes = rootElement.nodes("metadata/workflow/notificationlist/field/entry[value=\""+oldDn+"\"]");
	for (var i = 0 ; i < notificationNodes.length; i++) {
		notificationNodes[i].setStringValue("value", newDn);
		notificationNodes[i].setStringValue("label", newCn);
	}	
	
}	

function replaceActionUserOnTimeSheets(oldUser, newUser,siteId,projectId){
	import pe_workflow;
	var timesheetDB = null;
		var pendingTimesheetsView=null;
		try{
		timesheetDB = session.openDatabase("tg_pe_timesheet");
		timesheetDB.setAdministrationMode(true);
		var pendingTimesheetsQuery="siteid='"+siteId+"' and projectid='"+projectId+"' and FB_ACTIONUSERS='"+StringUtil.encodeToJavaString(oldUser.getDN())+"' AND status='Submitted'";
		pendingTimesheetsView = timesheetDB.openView("allweeklytimesheetsbydocumentid",pendingTimesheetsQuery);
		var docIds = pendingTimesheetsView.getAllDocumentIds();
		for (var i = 0 ; i < docIds.length; i++) {
			var pendingTimesheet = timesheetDB.getDocumentById(docIds[i]);
			pendingTimesheet.getWorkflowContext().reassignTask(oldUser,newUser,false);
			pendingTimesheet.save();			
			pendingTimesheet.close();
		}
	}finally{
		if (pendingTimesheetsView!=null){
			pendingTimesheetsView.close();
		}
		timesheetDB.setAdministrationMode(true);
		if(timesheetDB!=null){
			timesheetDB.close();
		}
	}
}

function replaceUserInDefaultWorkflow(oldDN, newDN,newCN,siteId, projectId){
	var workflowDB = null;
	var userDefaultWfView = null;
		
	var docDB=null;
	var siteDocTypesView = null;
	var siteDocTypes = null;
		
	var supportDB=null;
	var issueTypesView=null;
	var issueTypes = null;
	try{
		workflowDB = session.openDatabase("tg_pe_workflow");
		userDefaultWfView = workflowDB.openView("alldefaultworkflowsbysiteidprojectidandschema","siteid='"+siteId+"' and projectid='"+projectId+"' and wfapprover='"+StringUtil.encodeToJavaString(oldDN)+"'");
		var docIds = userDefaultWfView.getAllDocumentIds();
		for (var j = 0 ; j < docIds.length; j++) {
			var userDefaultWfDocument = workflowDB.getDocumentById(docIds[j]);
			var approvalSteps =  userDefaultWfDocument.nodes("/defaultworkflow/workflow/step");
			for (var i=0; i<approvalSteps.length; i++){
				var approverNode = approvalSteps[i].nodes("approver[dn=\""+oldDN+"\"]")[0];
				if(approverNode!=null){
					var newapprover =  approvalSteps[i].nodes("approver[dn=\""+newDN+"\"]")[0];
					if(newapprover==null){
						approverNode.setStringValue("dn",newDN);
						approverNode.setStringValue("cn",newCN);
					}else{
						approverNode.detach();
					}
				}
			}	
			
			var notificationNodes = userDefaultWfDocument.nodes("/defaultworkflow/workflow/notificationlist/field/entry[value=\""+oldDN+"\"]");
			for (var i = 0 ; i < notificationNodes.length; i++) {
				notificationNodes[i].setStringValue("value", newDN);
				notificationNodes[i].setStringValue("label", newCN);
			}
	
			userDefaultWfDocument.save();
			userDefaultWfDocument.close();
		}
			
		//also replace in workflow settings for document types and issue types
		docDB=session.openDatabase("tg_pe_document");
		siteDocTypesView = docDB.openView("alldocumenttypesdescbyid","siteid='"+siteId+"'");
		var docIds = siteDocTypesView.getAllDocumentIds();
		for (var j = 0 ; j < docIds.length ; j++) {
 			var documentTypeDoc = docDB.getDocumentById(docIds[j]);
			var approvalSteps = documentTypeDoc.nodes("/documenttype/metadata/workflow/step");
			for (var i=0; i<approvalSteps.length; i++){
				var oldApprover=approvalSteps[i].nodes("approver[dn=\""+oldDN+"\"]")[0];
				if(oldApprover!=null){
					var newApprover=approvalSteps[i].nodes("approver[dn=\""+newDN+"\"]")[0];
					if(newApprover==null){
						oldApprover.setStringValue("dn",newDN);
						oldApprover.setStringValue("cn",newCN);
					}else{
						oldApprover.detach();
					}
				}
			}	
			documentTypeDoc.save();
			documentTypeDoc.close();
		}
			
		//issue types
		supportDB=session.openDatabase("tg_pe_support");
		issueTypesView = supportDB.openView("allissuetypesbysiteidprojectidandid","siteid='"+siteId+"'");
		var docIds = issueTypesView.getAllDocumentIds();
		for (var j = 0 ; j < docIds.length ; j++) {
			var issueTypeDoc = supportDB.getDocumentById(docIds[j]);
			var approvalSteps = issueTypeDoc.nodes("/issuetype/metadata/workflow/step");
			for (var i=0; i<approvalSteps.length; i++){
				var issueapprover=approvalSteps[i].nodes("approver[dn=\""+oldDN+"\"]")[0];
				if(issueapprover!=null){
					var newissueapprover =  approvalSteps[i].nodes("approver[dn=\""+newDN+"\"]")[0];
				if (newissueapprover==null){
					issueapprover.setStringValue("dn",newDN);
					issueapprover.setStringValue("cn",newCN);
				}else{
					issueapprover.detach();
				}
			}
			issueTypeDoc.save();
			issueTypeDoc.close();
			}
		}
	} finally{
		if(userDefaultWfView!=null){
			userDefaultWfView.close();
		}
		if(siteDocTypesView!=null){
			siteDocTypesView.close();
		}
		if(docDB!=null){
			docDB.close();
		}	
		if(issueTypesView!=null){
			issueTypesView.close();
		}
		if(supportDB!=null){
			supportDB.close();
		}
		if (workflowDB != null) {
			workflowDB.close();
		}	
	}

}
function replaceUserInDefaultSecurity(oldDN, newDN,newCN,siteId, projectId){
	var securityDB = null;
	var userDefaultSecurityView = null;
		
	var docDB=null;
	var siteDocTypesView = null;
		
	var supportDB=null;
	var issueTypesView=null;
		
	try{
		securityDB = session.openDatabase("tg_pe_security");
		userDefaultSecurityView = securityDB.openView("alldefaultsecuritiesbysiteidprojectidandschema","siteid='"+siteId+"' and projectid='"+projectId+"' and (readeruser='"+StringUtil.encodeToJavaString(oldDN)+"' or editoruser='"+StringUtil.encodeToJavaString(oldDN)+"' or deniedreaduser='"+StringUtil.encodeToJavaString(oldDN)+"' or deniededituser='"+StringUtil.encodeToJavaString(oldDN)+"')");
		var docIds = userDefaultSecurityView.getAllDocumentIds();
			
		for (var j = 0 ; j < docIds.length ; j++) {	
			var userDefaultSecurityDocument = securityDB.getDocumentById(docIds[j]);
			var readerNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/readers/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(readerNode!=null){
				//only add if not already reader
				var newReaderNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/readers/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if (newReaderNode==null){
					readerNode.setStringValue("value",newDN);
					readerNode.setStringValue("label",newCN);
				}else{
					readerNode.detach();
				}
			}
			var editorNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/editors/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(editorNode!=null){
				//only add if not already editor
				var newEditorNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/editors/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if(newEditorNode==null){
					editorNode.setStringValue("value",newDN);
					editorNode.setStringValue("label",newCN);
				}else{
					editorNode.detach();
				}
			}
			var denyreadNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/denyread/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(denyreadNode!=null){
				//only add if not already denyread
				var newdenyreadNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/denyread/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if(newdenyreadNode==null){
					denyreadNode.setStringValue("value",newDN);
					denyreadNode.setStringValue("label",newCN);
				}else{
					denyreadNode.detach();
				}
			}
			var denyeditNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/denyedit/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(denyeditNode!=null){
				var newdenyeditNode = userDefaultSecurityDocument.nodes("/defaultsecurity/security/denyedit/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if(newdenyeditNode==null){	
					denyeditNode.setStringValue("value",newDN);
					denyeditNode.setStringValue("label",newCN);
				} else{
					denyeditNode.detach();
				}
			}
			userDefaultSecurityDocument.save();
			userDefaultSecurityDocument.close();
		}
			
		//also replace in the security for document and issue types
		docDB=session.openDatabase("tg_pe_document");
		siteDocTypesView = docDB.openView("alldocumenttypesdescbyid","siteid='"+siteId+"'");
		var docIds = siteDocTypesView.getAllDocumentIds();
		for (var j = 0 ; j < docIds.length ; j++) {	
			var documentTypeDoc = docDB.getDocumentById(docIds[j]);
			var readerNode = documentTypeDoc.nodes("/documenttype/metadata/security/readers/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(readerNode!=null){
			var newReaderNode = documentTypeDoc.nodes("/documenttype/metadata/security/readers/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if (newReaderNode==null){
					readerNode.setStringValue("value",newDN);
					readerNode.setStringValue("label",newCN);
				}else{
					readerNode.detach();
				}
			}
			var editorNode = documentTypeDoc.nodes("/documenttype/metadata/security/editors/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(editorNode!=null){
				var newEditorNode = documentTypeDoc.nodes("/documenttype/metadata/security/editors/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if (newEditorNode==null){
					editorNode.setStringValue("value",newDN);
					editorNode.setStringValue("label",newCN);
				}else{
					editorNode.detach();
				}
			}
			var denyreadNode = documentTypeDoc.nodes("/documenttype/metadata/security/denyread/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(denyreadNode!=null){
				var newdenyreadNode = documentTypeDoc.nodes("/documenttype/metadata/security/denyread/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if (newdenyreadNode==null){
					denyreadNode.setStringValue("value",newDN);
					denyreadNode.setStringValue("label",newCN);
				}else{
					denyreadNode.detach();
				}
			}
			var denyeditNode = documentTypeDoc.nodes("/documenttype/metadata/security/denyedit/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(denyeditNode!=null){
				var newdenyeditNode = documentTypeDoc.nodes("/documenttype/metadata/security/denyedit/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if (newdenyreadNode==null){
					denyeditNode.setStringValue("value",newDN);
					denyeditNode.setStringValue("label",newCN);
				}else{
					denyeditNode.detach();
				}
			}
			documentTypeDoc.save();
			documentTypeDoc.close();
		}
			
		//issue types
		supportDB=session.openDatabase("tg_pe_support");
		issueTypesView = supportDB.openView("allissuetypesbysiteidprojectidandid","siteid='"+siteId+"'");
		var docIds = issueTypesView.getAllDocumentIds();
		for (var j = 0 ; j < docIds.length ; j++) {	
			var issueTypeDoc = supportDB.getDocumentById(docIds[j]);
			var readerNode = issueTypeDoc.nodes("/issuetype/metadata/security/readers/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(readerNode!=null){
				var newReaderNode = issueTypeDoc.nodes("/issuetype/metadata/security/readers/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if (newReaderNode==null){
					readerNode.setStringValue("value",newDN);
					readerNode.setStringValue("label",newCN);
				}else{
					readerNode.detach();	
				}
			}
			var editorNode = issueTypeDoc.nodes("/issuetype/metadata/security/editors/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(editorNode!=null){
				var neweditorNode = issueTypeDoc.nodes("/issuetype/metadata/security/editors/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if (neweditorNode==null){
					editorNode.setStringValue("value",newDN);
					editorNode.setStringValue("label",newCN);
				}else{
					editorNode.detach();
				}
			}
			var denyreadNode = issueTypeDoc.nodes("/issuetype/metadata/security/denyread/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(denyreadNode!=null){
				var newdenyreadNode = issueTypeDoc.nodes("/issuetype/metadata/security/denyread/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if(newdenyreadNode==null){
					denyreadNode.setStringValue("value",newDN);
					denyreadNode.setStringValue("label",newCN);
				}else{
					denyreadNode.detach();
				}
			}
			var denyeditNode = issueTypeDoc.nodes("/issuetype/metadata/security/denyedit/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
			if(denyeditNode!=null){
				var newdenyeditNode = issueTypeDoc.nodes("/issuetype/metadata/security/denyedit/field[name='user']/entry[value=\""+newDN+"\"]")[0];
				if(newdenyeditNode){
					denyeditNode.setStringValue("value",newDN);
					denyeditNode.setStringValue("label",newCN);
				}else{
					denyeditNode.detach();
				}
			}
			issueTypeDoc.save();
			issueTypeDoc.close();
		}
	} finally{
		if(userDefaultSecurityView!=null){
			userDefaultSecurityView.close();
		}
		if(securityDB!=null){
			securityDB.close();
		}
		if(siteDocTypesView!=null){
			siteDocTypesView.close();
		}
		if(docDB!=null){
			docDB.close();
		}	
		if(issueTypesView!=null){
			issueTypesView.close();
		}
		if(supportDB!=null){
			supportDB.close();
		}
	}	
}

function replaceUserOnSite(oldDN, oldCN, newDN, newCN, siteId, replaceTasks, replaceIssues, replaceDocuments, replaceChanges, replaceTimeSheets, replaceDefaultWf, replaceDefaultSecurity){
	import pe_util;
	
	// warning, if we replace a user by himself, the result is buggy (user is not affected anymore to its tasks).
	if (oldDN==newDN) return;
	
	var projectIds = getProjectIDsListBySiteAndUser(siteId,oldDN);
	
	try {
		
	//check that tasks not locked
	if(replaceTasks){
		
		var alreadyLocked = false;
		//try to lock all user's tasks (pending and in progress) first
		var scheduleDB=null;
		var view = null;
		var pendingTasksCollection =null;
		var pendingTasksArray = new Array();
		var taskIndex = 0;
		try{
			scheduleDB= session.openDatabase("tg_pe_schedule");
			view = scheduleDB.openView("alltasksbysiteidprojectidandwbssortedid", "status != 'Done' and istemplate=false and resourcedn='"+StringUtil.encodeToJavaString(oldDN)+"' and siteid='"+siteId+"'");
			pendingTasksCollection = view.getAllDocuments();
			var taskDoc = pendingTasksCollection.getFirstDocument();
			var taskProjects=new Array();
			while(taskDoc!=null){
				try{
					taskDoc.lock(300);
				}catch(e){
					alreadyLocked = true;
					break;
				}
				pendingTasksArray[taskIndex]=taskDoc;
				var projectId=taskDoc.getStringValue("/task/projectid");
				addToArrayIfNotPresent(taskProjects, projectId);
				
				taskIndex++;
				taskDoc = pendingTasksCollection.getNextDocument();
			}
					
			if (alreadyLocked) {
				//unlock all the ones we locked
				for (var i = 0; i < pendingTasksArray.length; i++) {
					pendingTasksArray[i].unlock();
					pendingTasksArray[i].close();
				}
				return 2; //"Some of the user's tasks were already locked. Please try again later.";					
			}
			
			if (taskIndex>0){
				replaceUserOnTasks(oldDN, newDN, newCN, pendingTasksArray);
				
				// we need to reschedule the projects
				for (var i= 0; i < taskProjects.length; i++) {
					var result=com.triloggroup.pe.schedule.ScheduleUtil.runFullReschedule(session,siteId,taskProjects[i],false/*isTemplate*/,false/*sendstartDateAlert*/);
					if (result.getErrorCode() != com.triloggroup.pe.schedule.SchedulingResult.SUCCESS){
						if (result.getErrorCode() == com.triloggroup.project.schedule.ScheduleCst.ERROR_LOCKING_SCHEDULE){
							return 2; //"Some of the user's tasks were already locked. Please try again later."
						} else {
							return com.triloggroup.project.schedule.ScheduleCst.UNKNOWN_ERROR;
						}
					}
				}
				
			}
			replaceWBSSupervisorsInWBS(oldDN, newDN, newCN, scheduleDB, siteId);

		}finally{
			if (pendingTasksCollection != null) {
				pendingTasksCollection.close();
			}
			if (view != null) view.close();
			if (scheduleDB!=null)	scheduleDB.close();
		}
	}
	
	for(var i=0;i<projectIds.length;i++){
		
		//set bizdap users to reassign workflow 
		var oldUser = new BizDAPUser();
		oldUser.setName(oldCN);
		oldUser.setDN(oldDN);
		var newUser = new BizDAPUser();
		newUser.setDN(newDN);
		newUser.setName(newCN);
		replaceActionUserOnProject(oldUser, newUser,siteId,projectIds[i],replaceIssues,replaceDocuments,replaceChanges,replaceTimeSheets);
		if(replaceDefaultSecurity){
			replaceUserInDefaultSecurity(oldDN, newDN,newCN,siteId, projectIds[i]);
		}
		if(replaceDefaultWf){
			replaceUserInDefaultWorkflow(oldDN, newDN,newCN,siteId, projectIds[i]);
		}
		
		
		//add user to project if necessary
		var projectUsers = session.getLookupValues("tg_pe_project","allusersbysiteidprojectidanddn",siteId + "|" + projectIds[i] ,"userdn");
		if (@IsMember(newDN, projectUsers) == 0) { 
			// do not add the user if already present in the project
			var oldUserRole = getUserLocalRole(siteId, projectIds[i], oldDN);
			var unregistered = false;
			if(context.getDirectory().getDirectoryUser(newDN, true/*skipgroups*/)==null){
				unregistered = true;
			}
		 	com.triloggroup.pe.administration.AdministrationUtil.createUserDocument(context, newDN,newCN,oldUserRole,
	 		""/*team*/,projectIds[i],false/*isTemplate*/,null/*calendarId*/,null/*msuid*/, unregistered,""/*unregisteredUserEmail*/,siteId);
		}
	}
	
	if (replaceDefaultSecurity){
		//also replace default security for document types and issue types
		var securityDB = null;
		var typesSecurityView = null;
		var typesSecurityDocs = null;
		try{
			securityDB=session.openDatabase("tg_pe_security");
			typesSecurityView = securityDB.openView("alldefaultsecuritiesbysiteidandschema","siteid='"+siteId+"' and (schema='pe_documenttype' or schema='pe_issue_type') and (readeruser='"+StringUtil.encodeToJavaString(oldDN)+"' or editoruser='"+StringUtil.encodeToJavaString(oldDN)+"' or deniedreaduser='"+StringUtil.encodeToJavaString(oldDN)+"' or deniededituser='"+StringUtil.encodeToJavaString(oldDN)+"')");
			typesSecurityDocs = typesSecurityView.getAllDocuments();
			var typeSecurityDocument = typesSecurityDocs.getFirstDocument();
			while (typeSecurityDocument!=null){
				var readerNode = typeSecurityDocument.nodes("/defaultsecurity/security/readers/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
				if(readerNode!=null){
					var	newreaderNode = typeSecurityDocument.nodes("/defaultsecurity/security/readers/field[name='user']/entry[value=\""+newDN+"\"]")[0];
					if(newreaderNode==null){
						readerNode.setStringValue("value",newDN);
						readerNode.setStringValue("label",newCN);
					} else{
						readerNode.detach();
					}
				}
				var editorNode = typeSecurityDocument.nodes("/defaultsecurity/security/editors/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
				if(editorNode!=null){
					var	neweditorNode = typeSecurityDocument.nodes("/defaultsecurity/security/editors/field[name='user']/entry[value=\""+newDN+"\"]")[0];
					if(neweditorNode==null){
						editorNode.setStringValue("value",newDN);
						editorNode.setStringValue("label",newCN);
					} else{
						editorNode.detach();
					}
				}
				var denyreadNode = typeSecurityDocument.nodes("/defaultsecurity/security/denyread/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
				if(denyreadNode!=null){
					var	newdenyreadNode = typeSecurityDocument.nodes("/defaultsecurity/security/denyread/field[name='user']/entry[value=\""+newDN+"\"]")[0];
					if(newdenyreadNode==null){
						denyreadNode.setStringValue("value",newDN);
						denyreadNode.setStringValue("label",newCN);
					}else{
						denyreadNode.detach();
					}
				}
				var denyeditNode = typeSecurityDocument.nodes("/defaultsecurity/security/denyedit/field[name='user']/entry[value=\""+oldDN+"\"]")[0];
				if(denyeditNode!=null){
					var	newdenyeditNode = typeSecurityDocument.nodes("/defaultsecurity/security/denyedit/field[name='user']/entry[value=\""+newDN+"\"]")[0];
					if(newdenyeditNode==null){
						denyeditNode.setStringValue("value",newDN);
						denyeditNode.setStringValue("label",newCN);
					}else{
						denyeditNode.detach();
					}
				}
				typeSecurityDocument.save();
				typeSecurityDocument = typesSecurityDocs.getNextDocument();
			}
		}finally{
			if(typesSecurityDocs!=null)	typesSecurityDocs.close();
			if(typesSecurityView!=null)	typesSecurityView.close();
			if(securityDB!=null) securityDB.close();
		}
	}
	
	}catch(e){
		e.printStackTrace();
		return com.triloggroup.project.schedule.ScheduleCst.UNKNOWN_ERROR;
	}
}

// utility function
function addToArrayIfNotPresent(array, value){
	var idx=0;
	while (idx<array.length){
		if (array[idx]==value) return;
		idx++;
	}
	array[idx]=value;
}

function replaceWBSSupervisorsInWBS(oldDN, newDN, newCN, scheduleDB, siteId, projectId) {
	var wbsView = null;
	
	try {
		var wbsSubquery = "resourcedn=\""+StringUtil.encodeToJavaString(oldDN)+"\" and siteid=\""+siteId+"\"";
		if (projectId != null && projectId != "") {
			wbsSubquery += " and projectid=\""+projectId+"\"";
		}	
		
		wbsView =  scheduleDB.openView("allwbsdescbyid", wbsSubquery);
		var wbsDocIds = wbsView.getAllDocumentIds();
		if (wbsDocIds != null && wbsDocIds.length > 0) {
			// lock wbses to update
			try {
				scheduleDB.lock(wbsDocIds, com.triloggroup.project.schedule.ScheduleCst.LOCK_DELAY);
			}
			catch (e) {
				print(e.toString());
				return 2;
			}	
			finally {
				scheduleDB.unlock(wbsDocIds);
				if (wbsView != null) {
					wbsView.close();
				}	
			}	
			
			// update wbs documents
			for (var i = 0 ; i < wbsDocIds.length; i++) {
				var wbsDoc = scheduleDB.getDocumentById(wbsDocIds[i]);
				if (wbsDoc != null) {
					var resourceNode = wbsDoc.nodes("/wbs/wbssupervisors/user[dn=\""+oldDN+"\"]")[0];
					if (resourceNode != null) {
						resourceNode.setStringValue("dn", newDN);
						resourceNode.setStringValue("cn", newCN);
					}	
					wbsDoc.save();
					wbsDoc.close();
				}	
			}	
		}
	}
	catch (e) {
		print("replaceWBSSupervisorsInWBS: " + e.toString());
		return com.triloggroup.project.schedule.ScheduleCst.UNKNOWN_ERROR;
	}	
	finally {
		if (wbsView != null) {
			wbsView.close();
		}	
	}	
}	