From 4ee2837c72d94adbb39850838b02d9e26f25b7ca Mon Sep 17 00:00:00 2001
From: fred-fri <fred-fri@dsv.su.se>
Date: Tue, 29 May 2012 11:49:20 +0900
Subject: [PATCH] refactored addUnexistingUnitsAsKeywords method to use new
 Unit entity

---
 .../dsv/scipro/io/facade/ImporterFacade.java  | 1207 +++++++++--------
 .../dsv/scipro/springdata/repos/UnitRepo.java |    2 +-
 .../serviceimpls/UnitServiceImpl.java         |   11 +
 .../springdata/services/UnitService.java      |    5 +-
 4 files changed, 629 insertions(+), 596 deletions(-)

diff --git a/src/main/java/se/su/dsv/scipro/io/facade/ImporterFacade.java b/src/main/java/se/su/dsv/scipro/io/facade/ImporterFacade.java
index 8faffac2e3..d34bea52a4 100644
--- a/src/main/java/se/su/dsv/scipro/io/facade/ImporterFacade.java
+++ b/src/main/java/se/su/dsv/scipro/io/facade/ImporterFacade.java
@@ -44,168 +44,178 @@ import se.su.dsv.scipro.match.dao.interfaces.KeywordTypeDao;
 import se.su.dsv.scipro.match.dao.interfaces.SupervisorDao;
 import se.su.dsv.scipro.match.dataobject.Keyword;
 import se.su.dsv.scipro.springdata.services.MessageBoardService;
+import se.su.dsv.scipro.springdata.services.UnitService;
 
 /**
  * Main service facade for all importing operations.
- * The intent is that methods attached to this facade persists and merges incoming DTO-style objects into locally managed DomainObjects. 
+ * The intent is that methods attached to this facade persists and merges incoming DTO-style objects into locally managed DomainObjects.
  */
 @Service
 public class ImporterFacade {
-	@Autowired
-	private UserDao userDao;
-	@Autowired
-	private RoleDao roleDao;
-	@Autowired
-	private ProjectDao projectDao;
-	@Autowired
-	private UsernameDao usernameDao;
-	@Autowired
-	private ProjectClassDao projectClassDao;
-	@Autowired
-	private ProjectFollowerDao projectFollowerDao;
-	@Autowired
-	private SupervisorDao supervisorDao;
-	@Autowired
-	private ExternalImporter externalImporter;
-	@Autowired
-	private FinalSeminarDao finalSeminarDao;
-	@Autowired
-	private KeywordDao keywordDao;
-	@Autowired
-	private KeywordTypeDao keywordTypeDao;
-	@Autowired
-	private FinalSeminarActiveParticipationDao finalSeminarActiveParticipationDao;
-	@Autowired
-	private FinalSeminarOppositionDao finalSeminarOppositionDao;
+
+    @Autowired
+    private UnitService unitService;
+
+    @Autowired
+    private UserDao userDao;
+    @Autowired
+    private RoleDao roleDao;
+    @Autowired
+    private ProjectDao projectDao;
+    @Autowired
+    private UsernameDao usernameDao;
+    @Autowired
+    private ProjectClassDao projectClassDao;
+    @Autowired
+    private ProjectFollowerDao projectFollowerDao;
+    @Autowired
+    private SupervisorDao supervisorDao;
+    @Autowired
+    private ExternalImporter externalImporter;
+    @Autowired
+    private FinalSeminarDao finalSeminarDao;
+    @Autowired
+    private KeywordDao keywordDao;
+    @Autowired
+    private KeywordTypeDao keywordTypeDao;
+    @Autowired
+    private FinalSeminarActiveParticipationDao finalSeminarActiveParticipationDao;
+    @Autowired
+    private FinalSeminarOppositionDao finalSeminarOppositionDao;
     @Autowired
     MessageBoardService messageBoardService;
-	@PersistenceContext
-	private EntityManager entityManager;
-	private transient Logger logger = Logger.getLogger(ImporterFacade.class);
+    @PersistenceContext
+    private EntityManager entityManager;
+    private transient Logger logger = Logger.getLogger(ImporterFacade.class);
 
     /**
-	 * If the supplied user is null, a new one will be created and persisted.
-	 * Does not handle transient User instances, you probably have to do a dao-query for it before running this method.
-	 * @param user  hte user
-	 * @param dtoUser  the dtoUser
-	 */
-	@Transactional
-	public void mergeUser(final User user, final UserDTO dtoUser){
-		User userToMerge = (user!=null?user:new User());
-		if(userToMerge.getId() == null) //New user
-			userToMerge = userDao.save(userToMerge);
-		userFromDTO(userToMerge,dtoUser,true);
-	}
-	@Transactional
-	public void mergeProject(final Project project, final ProjectDTO dtoProject){
-		Project projectToMerge = (project!=null?project:new Project());
-		projectFromDTO(projectToMerge,dtoProject,true);
-	}
-	/**
-	 * Utility method for translating between DTO/DomainObject.
-	 */
-	private void userFromDTO(final User user,final UserDTO userDTO, boolean mergeLinkedEntities){
-		user.setEmailAddress(userDTO.email);
-		user.setFirstName(userDTO.firstName);
-		user.setLastName(userDTO.lastName);
-		user.setIdentifier(userDTO.id);
-		if(mergeLinkedEntities){
-			mergeLinkedUsernames(user,userDTO.usernames);
-			mergeLinkedProjects(userDTO.projects);
-			mergeLinkedRoles(user,userDTO.roles);
-			mergeLinkedResearchAreas(user, userDTO.researchAreas);
-		}
-	}
-	
-	private void mergeLinkedUsernames(final User user, final Set<UsernameDTO> userNames){
-		final Set<Username> currentUserNames = user.getUserNames();
-		final Set<UsernameDTO> userNamesInput = new HashSet<UsernameDTO>(userNames);//Defensive copy
-		final Set<Username> usernamesToRemove = new HashSet<Username>();
-		logger.debug("Current usernames: " + currentUserNames);
-		for(Username curUname:currentUserNames){
-			final UsernameDTO translatedCurUname = dtoFromUsername(curUname);
-			if(userNamesInput.contains(translatedCurUname)){
-				logger.debug("The user name: " + translatedCurUname + " exists in input, skipping");
-				userNamesInput.remove(translatedCurUname);
-			}else{
-				logger.debug("The user name: " + translatedCurUname + " does not exist in input, removing");
-				usernamesToRemove.add(curUname);
-			}
-		}
-		logger.debug("List to remove:" + usernamesToRemove);
-		logger.debug("List to add: " + userNamesInput);
-		//Remove unwanted usernames
-		for(Username unameToRemove : usernamesToRemove){
-			usernameDao.delete(unameToRemove);
-			user.getUserNames().remove(unameToRemove);
-		}
-		//Add wanted usernames
-		for(UsernameDTO unameDTOToAdd : userNamesInput){
-			Username unameToAdd = new Username();
-			userNameFromDTO(unameToAdd,unameDTOToAdd);
-			unameToAdd.setUser(user);
-			unameToAdd = usernameDao.save(unameToAdd);
-			user.addUserName(unameToAdd);
-		}
-	}
-	private void mergeLinkedProjects(final Set<ProjectDTO> projects){
-		for(final ProjectDTO projectDTO : projects){
-			logger.debug("Linking users to project: '"+projectDTO+"'");
-			Project project = projectDao.getProjectByIdentifier(projectDTO.id);
-			if(project == null){
-				logger.info("External project: '"+projectDTO+"' has no local representation, creating");
-				project = new Project();
-			}
-			projectFromDTO(project,projectDTO,true);
-		}
-	}
-	private void mergeLinkedRoles(final User user, final Set<UserRoleDTO> roles){
-		for(final UserRoleDTO roleDTO : roles){
-			logger.debug("Making role: "+roleDTO.role+ " for user: "+user);
-			if(roleDTO.role.equals(UserRoleDTO.EXTERNAL_USER_ROLES.AUTHOR_ROLE.asExternal())){
-				roleDao.makeStudent(user);
-			}
-			if(roleDTO.role.equals(UserRoleDTO.EXTERNAL_USER_ROLES.SUPERVISOR_ROLE.asExternal())){
-				roleDao.makeEmployee(user);
-			}
-			if(roleDTO.role.equals(UserRoleDTO.EXTERNAL_USER_ROLES.ADMIN_ROLE.asExternal())){
-				roleDao.makeAdmin(user);
-			}
-		}
-	}
-	private void projectFromDTO(Project project, final ProjectDTO projectDTO, boolean mergeLinkedEntities) {
-		project.setIdentifier(projectDTO.id);
-		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
-		try {
-			project.setDaisyStartDate(format.parse(projectDTO.startDate));
-		} catch (ParseException e) {
-			e.printStackTrace();
-		}
-		project.setTitle(projectDTO.title);
-		project.setProjectStatus(toLocalStatus(projectDTO.status));
-		ProjectClass externalProjectClass = toLocalClass(projectDTO);
-		if(externalProjectClass == null){
-			logger.warn("External project type: '"+projectDTO.type+ "' has no local representation, creating");
-			externalProjectClass = new ProjectClass();
-			externalProjectClass.setCode(projectDTO.type.toUpperCase().trim());
-			externalProjectClass.setName(projectDTO.type);
-			externalProjectClass.setDescription("Externally imported project class");
-			externalProjectClass = projectClassDao.save(externalProjectClass);
-		}
-		logger.debug("Using project class: "+ externalProjectClass+" to import project: "+projectDTO);
-		project.setProjectClass(externalProjectClass);
-		//Putting this here to trick the persistence api, the above assignments are mandatory, but the project is not allowed to be transient for the following to work
-		if(!entityManager.contains(project)){
+     * If the supplied user is null, a new one will be created and persisted.
+     * Does not handle transient User instances, you probably have to do a dao-query for it before running this method.
+     *
+     * @param user    hte user
+     * @param dtoUser the dtoUser
+     */
+    @Transactional
+    public void mergeUser(final User user, final UserDTO dtoUser) {
+        User userToMerge = (user != null ? user : new User());
+        if (userToMerge.getId() == null) //New user
+            userToMerge = userDao.save(userToMerge);
+        userFromDTO(userToMerge, dtoUser, true);
+    }
+
+    @Transactional
+    public void mergeProject(final Project project, final ProjectDTO dtoProject) {
+        Project projectToMerge = (project != null ? project : new Project());
+        projectFromDTO(projectToMerge, dtoProject, true);
+    }
+
+    /**
+     * Utility method for translating between DTO/DomainObject.
+     */
+    private void userFromDTO(final User user, final UserDTO userDTO, boolean mergeLinkedEntities) {
+        user.setEmailAddress(userDTO.email);
+        user.setFirstName(userDTO.firstName);
+        user.setLastName(userDTO.lastName);
+        user.setIdentifier(userDTO.id);
+        if (mergeLinkedEntities) {
+            mergeLinkedUsernames(user, userDTO.usernames);
+            mergeLinkedProjects(userDTO.projects);
+            mergeLinkedRoles(user, userDTO.roles);
+            mergeLinkedResearchAreas(user, userDTO.researchAreas);
+        }
+    }
+
+    private void mergeLinkedUsernames(final User user, final Set<UsernameDTO> userNames) {
+        final Set<Username> currentUserNames = user.getUserNames();
+        final Set<UsernameDTO> userNamesInput = new HashSet<UsernameDTO>(userNames);//Defensive copy
+        final Set<Username> usernamesToRemove = new HashSet<Username>();
+        logger.debug("Current usernames: " + currentUserNames);
+        for (Username curUname : currentUserNames) {
+            final UsernameDTO translatedCurUname = dtoFromUsername(curUname);
+            if (userNamesInput.contains(translatedCurUname)) {
+                logger.debug("The user name: " + translatedCurUname + " exists in input, skipping");
+                userNamesInput.remove(translatedCurUname);
+            } else {
+                logger.debug("The user name: " + translatedCurUname + " does not exist in input, removing");
+                usernamesToRemove.add(curUname);
+            }
+        }
+        logger.debug("List to remove:" + usernamesToRemove);
+        logger.debug("List to add: " + userNamesInput);
+        //Remove unwanted usernames
+        for (Username unameToRemove : usernamesToRemove) {
+            usernameDao.delete(unameToRemove);
+            user.getUserNames().remove(unameToRemove);
+        }
+        //Add wanted usernames
+        for (UsernameDTO unameDTOToAdd : userNamesInput) {
+            Username unameToAdd = new Username();
+            userNameFromDTO(unameToAdd, unameDTOToAdd);
+            unameToAdd.setUser(user);
+            unameToAdd = usernameDao.save(unameToAdd);
+            user.addUserName(unameToAdd);
+        }
+    }
+
+    private void mergeLinkedProjects(final Set<ProjectDTO> projects) {
+        for (final ProjectDTO projectDTO : projects) {
+            logger.debug("Linking users to project: '" + projectDTO + "'");
+            Project project = projectDao.getProjectByIdentifier(projectDTO.id);
+            if (project == null) {
+                logger.info("External project: '" + projectDTO + "' has no local representation, creating");
+                project = new Project();
+            }
+            projectFromDTO(project, projectDTO, true);
+        }
+    }
+
+    private void mergeLinkedRoles(final User user, final Set<UserRoleDTO> roles) {
+        for (final UserRoleDTO roleDTO : roles) {
+            logger.debug("Making role: " + roleDTO.role + " for user: " + user);
+            if (roleDTO.role.equals(UserRoleDTO.EXTERNAL_USER_ROLES.AUTHOR_ROLE.asExternal())) {
+                roleDao.makeStudent(user);
+            }
+            if (roleDTO.role.equals(UserRoleDTO.EXTERNAL_USER_ROLES.SUPERVISOR_ROLE.asExternal())) {
+                roleDao.makeEmployee(user);
+            }
+            if (roleDTO.role.equals(UserRoleDTO.EXTERNAL_USER_ROLES.ADMIN_ROLE.asExternal())) {
+                roleDao.makeAdmin(user);
+            }
+        }
+    }
+
+    private void projectFromDTO(Project project, final ProjectDTO projectDTO, boolean mergeLinkedEntities) {
+        project.setIdentifier(projectDTO.id);
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            project.setDaisyStartDate(format.parse(projectDTO.startDate));
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        project.setTitle(projectDTO.title);
+        project.setProjectStatus(toLocalStatus(projectDTO.status));
+        ProjectClass externalProjectClass = toLocalClass(projectDTO);
+        if (externalProjectClass == null) {
+            logger.warn("External project type: '" + projectDTO.type + "' has no local representation, creating");
+            externalProjectClass = new ProjectClass();
+            externalProjectClass.setCode(projectDTO.type.toUpperCase().trim());
+            externalProjectClass.setName(projectDTO.type);
+            externalProjectClass.setDescription("Externally imported project class");
+            externalProjectClass = projectClassDao.save(externalProjectClass);
+        }
+        logger.debug("Using project class: " + externalProjectClass + " to import project: " + projectDTO);
+        project.setProjectClass(externalProjectClass);
+        //Putting this here to trick the persistence api, the above assignments are mandatory, but the project is not allowed to be transient for the following to work
+        if (!entityManager.contains(project)) {
             boolean newProject = (project.getId() == null);
 
             project = projectDao.save(project);
 
-            if (newProject){
+            if (newProject) {
                 MessageBoard messageBoard = new MessageBoard(project);
                 messageBoard.setTitle(project.getTitle());
                 messageBoard = messageBoardService.save(messageBoard);
-            }
-            else {
+            } else {
                 MessageBoard messageBoard = messageBoardService.getMessageBoard(project);
                 messageBoard.setTitle(project.getTitle());
                 messageBoard = messageBoardService.save(messageBoard);
@@ -214,457 +224,466 @@ public class ImporterFacade {
         }
 
 
+        //Loop over all participants and assign roles
+        if (mergeLinkedEntities) {
+            checkForRemovedMembers(project, projectDTO.participants);
+            for (ProjectParticipantDTO projectParticipant : projectDTO.participants) {
+                projectParticipantFromDTO(project, projectParticipant);
+            }
+        }
+    }
+
+    private void checkForRemovedMembers(final Project project, final Set<ProjectParticipantDTO> participants) {
+        //Get project team members.
+        final Set<Member> currentMembers = new HashSet<Member>(project.getMembers());
+        final Set<ProjectParticipantDTO> remoteMembers = new HashSet<ProjectParticipantDTO>(participants);
+        final Set<Member> membersToRemove = new HashSet<Member>();
+        //Check to see if some members of the projects have been removed from Daisy. If so, we need to remove from Scipro as well.
+        for (Member m : currentMembers) {
+            logger.debug("Translating member " + m + " to DTO to compare with remote participants.");
+            ProjectParticipantDTO translated = participantDtoFromMember(m);
+            if (remoteMembers.contains(translated)) {
+                logger.debug(m + " exists on remote system, skipping.");
+                remoteMembers.remove(translated);
+            } else {
+                logger.info(m + " does not exist on remote system, removing from Scipro.");
+                membersToRemove.add(m);
+            }
+        }
+        //Removing member from Scipro.
+        for (Member m : membersToRemove) {
+            switch (m.getType()) {
+                case AUTHOR: {
+                    Student student = roleDao.findStudentRole(m.getUser());
+                    project.removeAuthor(student);
+                    break;
+                }
+                case SUPERVISOR: {
+                    project.removeSupervisor();
+                    break;
+                }
+                case CO_SUPERVISOR: {
+                    Employee emp = supervisorDao.getFrom(m.getUser());
+                    ProjectFollower pf = new ProjectFollower();
+                    pf.setProjectRole(ProjectTeamMemberRoles.CO_SUPERVISOR);
+                    pf.setFollower(emp);
+                    if (project.getProjectCoSupervisors().contains(pf))
+                        project.removeProjectFollower(pf);
+                    else
+                        logger.debug("Can't find project follower to remove.");
+                    break;
+                }
+                case REVIEWER: {
+                    Employee emp = supervisorDao.getFrom(m.getUser());
+                    ProjectFollower pf = new ProjectFollower();
+                    pf.setProjectRole(ProjectTeamMemberRoles.REVIEWER);
+                    pf.setFollower(emp);
+                    if (project.getProjectReviewers().contains(pf))
+                        project.removeProjectFollower(pf);
+                    else
+                        logger.debug("Can't find project follower to remove.");
+                    break;
+                }
+            }
+        }
 
 
+    }
 
-		//Loop over all participants and assign roles
-		if(mergeLinkedEntities){
-			checkForRemovedMembers(project, projectDTO.participants);
-			for(ProjectParticipantDTO projectParticipant:projectDTO.participants){
-				projectParticipantFromDTO(project,projectParticipant);
-			}
-		}
-	}
-	private void checkForRemovedMembers(final Project project, final Set<ProjectParticipantDTO> participants) {
-		//Get project team members.
-		final Set<Member> currentMembers = new HashSet<Member>(project.getMembers());  
-		final Set<ProjectParticipantDTO> remoteMembers = new HashSet<ProjectParticipantDTO>(participants);
-		final Set<Member> membersToRemove = new HashSet<Member>();
-		//Check to see if some members of the projects have been removed from Daisy. If so, we need to remove from Scipro as well.
-		for(Member m : currentMembers) {
-			logger.debug("Translating member "+m+" to DTO to compare with remote participants.");
-			ProjectParticipantDTO translated = participantDtoFromMember(m);
-			if(remoteMembers.contains(translated)){
-				logger.debug(m+" exists on remote system, skipping.");
-				remoteMembers.remove(translated);
-			} else {
-				logger.info(m+" does not exist on remote system, removing from Scipro.");
-				membersToRemove.add(m);
-			}
-		}
-		//Removing member from Scipro.
-		for(Member m : membersToRemove){
-			switch(m.getType()){
-			case AUTHOR: {
-				Student student = roleDao.findStudentRole(m.getUser());
-				project.removeAuthor(student);
-				break;
-			}
-			case SUPERVISOR: {
-				project.removeSupervisor();
-				break;
-			}
-			case CO_SUPERVISOR: {
-				Employee emp = supervisorDao.getFrom(m.getUser());
-				ProjectFollower pf = new ProjectFollower();
-				pf.setProjectRole(ProjectTeamMemberRoles.CO_SUPERVISOR);
-				pf.setFollower(emp);
-				if(project.getProjectCoSupervisors().contains(pf))
-					project.removeProjectFollower(pf);
-				else
-					logger.debug("Can't find project follower to remove.");
-				break;
-			}
-			case REVIEWER: {
-				Employee emp = supervisorDao.getFrom(m.getUser());
-				ProjectFollower pf = new ProjectFollower();
-				pf.setProjectRole(ProjectTeamMemberRoles.REVIEWER);
-				pf.setFollower(emp);
-				if(project.getProjectReviewers().contains(pf))
-					project.removeProjectFollower(pf);
-				else
-					logger.debug("Can't find project follower to remove.");
-				break;
-			}
-			}
-		}
-		
-		
-	}
-	private ProjectParticipantDTO participantDtoFromMember(Member m) {
-		ProjectParticipantDTO dto = new ProjectParticipantDTO();
-		PersonDTO person = new PersonDTO(m.getUser().getIdentifier());
-		dto.setPerson(person);
-		switch(m.getType()){
-		case AUTHOR: 
-			{
-			dto.setRole(EXTERNAL_PROJECT_ROLE.PARTICIPANT.name());
-			break;
-			}
-		case SUPERVISOR:
-			{
-			dto.setRole(EXTERNAL_PROJECT_ROLE.SUPERVISOR.name());
-			break;
-			}
-		case REVIEWER:
-			{
-			dto.setRole(EXTERNAL_PROJECT_ROLE.EXAMINER.name());
-			break;
-			}
-		case CO_SUPERVISOR:
-			{
-			dto.setRole(EXTERNAL_PROJECT_ROLE.ASSISTANT_SUPERVISOR.name());
-			break;
-			}
-		}
-		return dto;
-	}
-	private void projectParticipantFromDTO(final Project project, final ProjectParticipantDTO projectParticipant) {
-		//Use existing members to avoid duplicated roles being assigned
-		final List<Member> currentProjectMembers = project.getMembers();
-		logger.debug("Linking: "+projectParticipant);
-		User linkedUser = userDao.getUserByIdentifier(projectParticipant.person.id);
-		if(linkedUser == null){ //Attempt to import the user if it's a new one.
-			externalImporter.importUser(projectParticipant.person.id, false);
-			linkedUser = userDao.getUserByIdentifier(projectParticipant.person.id);
-			if(linkedUser == null){
-				logger.error("Can't import user with id: " + projectParticipant.person.id + " skipping assigning him/her to the project: "+ project);
-				return;
-			}
-		}
-		final ProjectParticipantDTO.LOCAL_PROJECT_ROLE localRole = extractLocalRole(projectParticipant.role);
-		if(localRole == null){//this is an unknown project role, warn and continue
-			logger.warn("Encountered an unknown project role ("+projectParticipant.role+") when importing project participant: "+projectParticipant.person.id +", the participant will be skipped");
-			return;
-		}
-		//Assign the local role to the participant, this is a lot of boilerplate code and should be made easier.
-		logger.debug("Assigning the role "+localRole+" for "+linkedUser+" on project "+project);
-		switch(localRole){
-			case PARTICIPANT:
-			{
-				//logger.debug("Assigning Participant role to "+projectParticipant.person.id);
-				final Member tmpMember = new Member(linkedUser,Member.Type.AUTHOR);
-				if(currentProjectMembers.contains(tmpMember)){
-					logger.debug("Skipping already assigned "+tmpMember.getType() + " user "+tmpMember.getUser());
-					return;//Skip if already assigned an author role
-				}
-				logger.debug("Making '" + linkedUser + "' an author");
-				final Student stud = roleDao.makeStudent(linkedUser);
-				project.getProjectParticipants().add(stud);
-				break;
-			}
-			case ACTIVE_PARTICIPANT:
-			{
-				final List<FinalSeminar> fsList = assureFinalSeminarAvailable(project);
-				//logger.debug("Assigning Active participation role to " + fsList.size() + " seminars for "+projectParticipant.person.id);
-				for(FinalSeminar fs : fsList){
-					if(userAlreadyAttachedAsParticipant(linkedUser,fs.getActiveParticipations()))
-						continue;
-					FinalSeminarActiveParticipation fsap = new FinalSeminarActiveParticipation();
-					fsap.setUser(linkedUser);
-					fsap.setFinalSeminar(fs);
-					fsap.setProject(project);
-					fsap = finalSeminarActiveParticipationDao.save(fsap);
-					fs.getActiveParticipations().add(fsap);
-				}
-				break;
-			}
-			case EXAMINER:
-			{
-				ProjectFollower pf = new ProjectFollower();
-				//logger.debug("Assigning Examiner role to "+projectParticipant.person.id);
-				final Member tmpMember = new Member(linkedUser,Member.Type.REVIEWER);
-				if(currentProjectMembers.contains(tmpMember)){
-					logger.debug("Skipping already assigned "+tmpMember.getType() + " user "+tmpMember.getUser());
-					return;//Skip if already assigned a Reviewer role
-				}
-				final Employee emp = roleDao.makeEmployee(linkedUser);
-				pf.setProjectRole(ProjectTeamMemberRoles.REVIEWER);
-				pf.setFollower(emp);
-				if(pf.getFollower() != null && pf.getProjectRole() != null){
-					pf.setProject(project);
-					pf = projectFollowerDao.save(pf);
-					project.getProjectFollowers().add(pf);
-				}
-				break;
-			}
-			case OPPONENT:
-			{
-				final List<FinalSeminar> fsList = assureFinalSeminarAvailable(project);
-				//logger.debug("Assigning Opponent role to " + fsList.size() + " seminars for "+projectParticipant.person.id);
-				for(FinalSeminar fs : fsList){
-					if(userAlreadyAttachedAsParticipant(linkedUser,fs.getOppositions()))
-						continue;
-					FinalSeminarOpposition fsop = new FinalSeminarOpposition();
-					final Student stud = roleDao.makeStudent(linkedUser);
-					fsop.setOpponent(stud);
-					fsop.setFinalSeminar(fs);
-					fsop.setProject(project);
-					fsop = finalSeminarOppositionDao.save(fsop);
-					fs.getOppositions().add(fsop);
-				}
-				break;
-			}
-			case SUPERVISOR:
-			{
-				//logger.debug("Assigning Supervisor role to "+projectParticipant.person.id);
-				final Member tmpMember = new Member(linkedUser,Member.Type.SUPERVISOR);
-				if(currentProjectMembers.contains(tmpMember)){
-					logger.debug("Skipping already assigned "+tmpMember.getType() + " user "+tmpMember.getUser());
-					return;//Skip if already assigned	a supervisor role
-				}
-				logger.debug("Making '" + linkedUser + "' a supervisor");
-				final Employee emp = roleDao.makeEmployee(linkedUser);
-				project.setHeadSupervisor(emp);
-				break;
-			}
-			case CO_SUPERVISOR:
-			{
-				ProjectFollower pf = new ProjectFollower();
-				//logger.debug("Assigning Co-supervisor role to "+projectParticipant.person.id);
-				final Member tmpMember = new Member(linkedUser,Member.Type.CO_SUPERVISOR);
-				if(currentProjectMembers.contains(tmpMember)){
-					logger.debug("Skipping already assigned "+tmpMember.getType() + " user "+tmpMember.getUser());
-					return;//Skip if already assigned	a co-supervisor role
-				}
-				final Employee emp = roleDao.makeEmployee(linkedUser);
-				pf.setProjectRole(ProjectTeamMemberRoles.CO_SUPERVISOR);
-				pf.setFollower(emp);
-				//Add the assigned PF to the project and save
-				if(pf.getFollower() != null && pf.getProjectRole() != null){
-					pf.setProject(project);
-					pf = projectFollowerDao.save(pf);
-					project.getProjectFollowers().add(pf);
-				}
-				break;
-			}
-		}
-	}
-	/*
-	 * Translate remote roles to local ones.
-	 */
-	private LOCAL_PROJECT_ROLE extractLocalRole(final String fromRemoteRole) {
-		if(fromRemoteRole == null)
-			return null;
-		for(EXTERNAL_PROJECT_ROLE externalRole : EXTERNAL_PROJECT_ROLE.values()){
-			if(fromRemoteRole.equalsIgnoreCase(externalRole.toString()))
-				return externalRole.toLocal();
-		}
-		return null;
-	}
-	private boolean userAlreadyAttachedAsParticipant(final User user,final List<? extends FinalSeminarParticipation> participantList) {
-		for(final FinalSeminarParticipation participant : participantList)
-			if(user.equals(participant.getUser()))
-				return true;
-		return false;
-	}
-	private List<FinalSeminar> assureFinalSeminarAvailable(final Project project) {
-		final List<FinalSeminar> fsList = finalSeminarDao.findFinalSeminarsByProject(project);
-		if(fsList.size() == 0){
-			logger.warn("No seminars registered for the project " + project + ", creating a default seminar dated according to start/end dates for the project");
-			FinalSeminar fs = new FinalSeminar();
-			fs.setProject(project);
-			fs.setRoom("n/a");
-			fs.setStartDate(project.getDaisyStartDate());
-			fs.setEndDate(project.getDaisyStartDate());
-			fs = finalSeminarDao.save(fs);
-			fsList.add(fs);
-		}
-		return fsList;
-	}
-	private void userNameFromDTO(final Username username, final UsernameDTO usernameDTO){
-		username.setUserName(usernameDTO.getUsername().toLowerCase().trim());
-		username.setRealm(usernameDTO.getRealm().toUpperCase().trim());
-	}
-	private UsernameDTO dtoFromUsername(final Username name){
-		UsernameDTO dto = new UsernameDTO();
-		dto.setUsername(name.getUserName().toLowerCase().trim());
-		dto.setRealm(name.getRealm().toUpperCase().trim());
-		return dto;
-	}
-	
-	private ProjectClass toLocalClass(final ProjectDTO projectDTO){
-		ProjectClass pClass = null;
-		final String extractedType = extractProjectType(projectDTO);
-		pClass = projectClassDao.getProjectClass(extractedType);
-		return pClass;
-	}
-	private String extractProjectType(ProjectDTO projectDTO) {
-		String extractedType = ProjectClass.UNKNOWN;
-		if(projectDTO.type != null){//Find class from project
-			extractedType = mapToLocalProjectClass(projectDTO.type);
-		}else{//Find class from participants as a fallback
-			for(ProjectParticipantDTO projectParticipant : projectDTO.participants){
-				if(projectParticipant.level != null){
-					extractedType = mapToLocalProjectClass(projectParticipant.level);
-					break;
-				}
-			}
-		}
-		logger.debug("Returning: "+extractedType+ " as the extracted type of the project: "+projectDTO);
-		return extractedType;
-	}
-	private String mapToLocalProjectClass(final String input){
-		if(input == null)
-			return null;
-		for(ProjectParticipantDTO.EXTERNAL_PROJECT_CLASS cls : ProjectParticipantDTO.EXTERNAL_PROJECT_CLASS.values()){
-			if(input.equalsIgnoreCase(cls.toString()))
-				return cls.toLocal();
-		}
-		return null;
-	}
-	private ProjectStatus toLocalStatus(String externalProjectStatus){
-		if(externalProjectStatus.equals("STARTED") || externalProjectStatus.equals("LATE")){
-			return ProjectStatus.ACTIVE;
-		}else if(externalProjectStatus.equals("FINISHED")){
-			return ProjectStatus.COMPLETED;
-		}else{
-			return ProjectStatus.INACTIVE;
-		}
-	}
-	
-	@Transactional
-	public void addUnitToSupervisor(PersonDTO supervisorDTO, UnitDTO unitDTO) {
-		User supervisorUser = userDao.getUserByIdentifier(supervisorDTO.id);
-		Employee supervisor = supervisorDao.getFrom(supervisorUser);
-		if(supervisor!=null){
-		List<Keyword> currentUnits = supervisor.getKeywords().getFiltered(keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
-		//If supervisor is already assigned to a unit, remove to make sure only the latest unit is being added since we only allow one unit in Scipro.
-		//Supervisor is not going to be allowed to have more than one unit in the future, but some have two in Daisy at the moment.
-		if (!currentUnits.isEmpty()) {
-			logger.info(supervisor.getUser().getFullName() + " is already attached to a unit and this is being overwritten.");
-			supervisor.getKeywords().getAll().removeAll(currentUnits);
-		}
-		Keyword unitToAdd = keywordDao.getKeywordByIdentifierAndType(unitDTO.id, keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
-		logger.debug("Adding unit: " + unitToAdd.getKeyword() + " to supervisor: " + supervisor.getUser().getFullName());
-		supervisor.getKeywords().getAll().add(unitToAdd);
-		} else {
-			logger.debug("Can't find supervisor: "+ supervisorDTO.id);
-		}
-	}
-	
-	private void mergeLinkedResearchAreas(final User user, final Set<ResearchAreaDTO> areas){
-			for(final ResearchAreaDTO researchAreaDTO : areas){
-			Keyword area = keywordDao.getKeywordByIdentifierAndType(researchAreaDTO.id, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
-			if(area == null){
-				logger.info("External research area: '"+researchAreaDTO+"' has no local representation, creating");
-				area = new Keyword(researchAreaDTO.name, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
-				area.setIdentifier(researchAreaDTO.id);
-				area = keywordDao.save(area);
-			} else {
-				logger.info("Research area " + area.getKeyword() + " already exists, skipping");
-			}
-			addResearchAreaToUser(user, area);
-			}	
-	}
-	
-	private void addResearchAreaToUser(User user, Keyword area) {
-		Employee supervisor = supervisorDao.getFrom(user);
-		logger.info("Adding research area: " + area.getKeyword() + " to supervisor " + supervisor.getUser().getFullName());
-		supervisor.getKeywords().getAll().add(area);
-	}
-	
-	@Transactional
-	public void addUnexistingResearchAreas(final Set<ResearchAreaDTO> areas) {
-		final Set<Keyword> currentAreas = keywordDao.getKeywords(keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA), true);
-		final Set<ResearchAreaDTO> remoteAreas = new HashSet<ResearchAreaDTO>(areas);
-		final Set<Keyword> areasToRemove = new HashSet<Keyword>();
-		//Compare remote with database
-		for (Keyword currentArea : currentAreas){
-			ResearchAreaDTO translatedArea = dtoFromAreaKeyword(currentArea);
-			if(!remoteAreas.contains(translatedArea)){
-				logger.info("Area " + translatedArea.getName() + " does not exist on remote, preparing to remove.");
-				areasToRemove.add(currentArea);
-			} 				
-		}
-		//Delete areas that not exist on remote
-		for (Keyword areaToRemove : areasToRemove){
-			keywordDao.delete(areaToRemove);
-			logger.debug("Deleted research area: " + areaToRemove.getKeyword() + " since it has been removed from remote system");
-		}
-		//Add areas to database
-		for(final ResearchAreaDTO researchAreaDTO : remoteAreas){
-			Keyword area = keywordDao.getKeywordByIdentifierAndType(researchAreaDTO.id, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
-			if(area == null){
-				logger.info("External research area: '"+researchAreaDTO+"' has no local representation, creating");
-				area = new Keyword(researchAreaDTO.name, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
-				area.setIdentifier(researchAreaDTO.id);
-				area = keywordDao.save(area);
-			}  else if (!area.getKeyword().equals(researchAreaDTO.name)){
-				logger.info("Research area " + area.getKeyword() + " has changed name, renaming to: " + researchAreaDTO.name);
-				area.setKeyword(researchAreaDTO.name);		
-			} else {
-				logger.info("Research area " + area.getKeyword() + " already exists, skipping");
-			}
-			if (researchAreaDTO.active.equals("false")){
-				logger.info(area.getKeyword() + " is inactivated on remote system.");
-				area.setDeleted(true);
-			}				
-		}
-	}
-	
-	@Transactional
-	public void addUnexistingUnitsAsKeywords(final Set<UnitDTO> unitsFromDTO) {
-		final Set<Keyword> currentUnits = keywordDao.getKeywords(keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT), true);
-		final Set<UnitDTO> remoteUnits = new HashSet<UnitDTO>(unitsFromDTO);
-		final Set<Keyword> unitsToRemove = new HashSet<Keyword>();
-		for (Keyword unit : currentUnits) {
-			UnitDTO translatedUnit = dtoFromUnitKeyword(unit);
-			if (!remoteUnits.contains(translatedUnit)) {
-				logger.info("Unit " + translatedUnit.getName() + " does not exist on remote, preparing to remove.");
-				unitsToRemove.add(unit);	
-			}
-		}
-		//Delete units that not exist on remote
-		for (Keyword unitToRemove : unitsToRemove){
-			keywordDao.delete(unitToRemove);
-			logger.debug("Deleted unit: " + unitToRemove.getKeyword() + " since it has been removed from remote system");
-		}
-		//Add units to database
-		for(final UnitDTO unitDTO : remoteUnits){
-			Keyword unit = keywordDao.getKeywordByIdentifierAndType(unitDTO.id, keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
-			if(unit == null){
-				logger.info("External unit: '"+unitDTO+"' has no local representation, creating");
-				unit = new Keyword(unitDTO.name, keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
-				unit.setIdentifier(unitDTO.id);
-				unit = keywordDao.save(unit);
-			}  else if (!unit.getKeyword().equals(unitDTO.name)){
-				logger.info("Unit " + unit.getKeyword() + " has changed name, renaming to: " + unitDTO.name);
-				unit.setKeyword(unitDTO.name);		
-			} else {
-				logger.info("Unit " + unit.getKeyword() + " already exists, skipping");
-			}				
-		}
-	}
-	
-	public void removeUnitFromSupervisorsNotInSet(Set<PersonDTO> supervisorSet) {
-		final Set<Employee> supervisorsWithRemoteUnit = new HashSet<Employee>();
-		final Set<Employee> currentSupervisors = new HashSet<Employee>(supervisorDao.findAll());
-		
-		//Create SciPro Employees from DTOs.
-		for (PersonDTO supervisorDTO : supervisorSet) {
-			User supervisorUser = userDao.getUserByIdentifier(supervisorDTO.id);
-			Employee supervisor = supervisorDao.getFrom(supervisorUser);
-			supervisorsWithRemoteUnit.add(supervisor);
-		}
-		
-		//Remove units from supervisors that is not in the remote set.
-		for (Employee supervisor : currentSupervisors) {
-			if(!supervisorsWithRemoteUnit.contains(supervisor)) {
-				logger.debug(supervisor.getNameAsString()+" does not have a remote unit. Searching for local units to remove.");
-				List<Keyword> unitsToRemove = supervisor.getKeywords().getFiltered(keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
-				if(!unitsToRemove.isEmpty()){
-					supervisor.getKeywords().getAll().removeAll(unitsToRemove);
-					logger.debug("Removed units from: " + supervisor.getNameAsString()); 
-				}
-			} 
-		}
-	}
-	
-	private UnitDTO dtoFromUnitKeyword(final Keyword unit){
-		UnitDTO dto = new UnitDTO();
-		dto.setName(unit.getKeyword());
-		if(unit.getIdentifier() != null)
-			dto.setId(unit.getIdentifier());
-		return dto;
-	}
-	
-	private ResearchAreaDTO dtoFromAreaKeyword(final Keyword area){
-		ResearchAreaDTO dto = new ResearchAreaDTO();
-		dto.setName(area.getKeyword());
-		if (area.getIdentifier() != null)
-			dto.setId(area.getIdentifier());
-		return dto;
-	}
+    private ProjectParticipantDTO participantDtoFromMember(Member m) {
+        ProjectParticipantDTO dto = new ProjectParticipantDTO();
+        PersonDTO person = new PersonDTO(m.getUser().getIdentifier());
+        dto.setPerson(person);
+        switch (m.getType()) {
+            case AUTHOR: {
+                dto.setRole(EXTERNAL_PROJECT_ROLE.PARTICIPANT.name());
+                break;
+            }
+            case SUPERVISOR: {
+                dto.setRole(EXTERNAL_PROJECT_ROLE.SUPERVISOR.name());
+                break;
+            }
+            case REVIEWER: {
+                dto.setRole(EXTERNAL_PROJECT_ROLE.EXAMINER.name());
+                break;
+            }
+            case CO_SUPERVISOR: {
+                dto.setRole(EXTERNAL_PROJECT_ROLE.ASSISTANT_SUPERVISOR.name());
+                break;
+            }
+        }
+        return dto;
+    }
+
+    private void projectParticipantFromDTO(final Project project, final ProjectParticipantDTO projectParticipant) {
+        //Use existing members to avoid duplicated roles being assigned
+        final List<Member> currentProjectMembers = project.getMembers();
+        logger.debug("Linking: " + projectParticipant);
+        User linkedUser = userDao.getUserByIdentifier(projectParticipant.person.id);
+        if (linkedUser == null) { //Attempt to import the user if it's a new one.
+            externalImporter.importUser(projectParticipant.person.id, false);
+            linkedUser = userDao.getUserByIdentifier(projectParticipant.person.id);
+            if (linkedUser == null) {
+                logger.error("Can't import user with id: " + projectParticipant.person.id + " skipping assigning him/her to the project: " + project);
+                return;
+            }
+        }
+        final ProjectParticipantDTO.LOCAL_PROJECT_ROLE localRole = extractLocalRole(projectParticipant.role);
+        if (localRole == null) {//this is an unknown project role, warn and continue
+            logger.warn("Encountered an unknown project role (" + projectParticipant.role + ") when importing project participant: " + projectParticipant.person.id + ", the participant will be skipped");
+            return;
+        }
+        //Assign the local role to the participant, this is a lot of boilerplate code and should be made easier.
+        logger.debug("Assigning the role " + localRole + " for " + linkedUser + " on project " + project);
+        switch (localRole) {
+            case PARTICIPANT: {
+                //logger.debug("Assigning Participant role to "+projectParticipant.person.id);
+                final Member tmpMember = new Member(linkedUser, Member.Type.AUTHOR);
+                if (currentProjectMembers.contains(tmpMember)) {
+                    logger.debug("Skipping already assigned " + tmpMember.getType() + " user " + tmpMember.getUser());
+                    return;//Skip if already assigned an author role
+                }
+                logger.debug("Making '" + linkedUser + "' an author");
+                final Student stud = roleDao.makeStudent(linkedUser);
+                project.getProjectParticipants().add(stud);
+                break;
+            }
+            case ACTIVE_PARTICIPANT: {
+                final List<FinalSeminar> fsList = assureFinalSeminarAvailable(project);
+                //logger.debug("Assigning Active participation role to " + fsList.size() + " seminars for "+projectParticipant.person.id);
+                for (FinalSeminar fs : fsList) {
+                    if (userAlreadyAttachedAsParticipant(linkedUser, fs.getActiveParticipations()))
+                        continue;
+                    FinalSeminarActiveParticipation fsap = new FinalSeminarActiveParticipation();
+                    fsap.setUser(linkedUser);
+                    fsap.setFinalSeminar(fs);
+                    fsap.setProject(project);
+                    fsap = finalSeminarActiveParticipationDao.save(fsap);
+                    fs.getActiveParticipations().add(fsap);
+                }
+                break;
+            }
+            case EXAMINER: {
+                ProjectFollower pf = new ProjectFollower();
+                //logger.debug("Assigning Examiner role to "+projectParticipant.person.id);
+                final Member tmpMember = new Member(linkedUser, Member.Type.REVIEWER);
+                if (currentProjectMembers.contains(tmpMember)) {
+                    logger.debug("Skipping already assigned " + tmpMember.getType() + " user " + tmpMember.getUser());
+                    return;//Skip if already assigned a Reviewer role
+                }
+                final Employee emp = roleDao.makeEmployee(linkedUser);
+                pf.setProjectRole(ProjectTeamMemberRoles.REVIEWER);
+                pf.setFollower(emp);
+                if (pf.getFollower() != null && pf.getProjectRole() != null) {
+                    pf.setProject(project);
+                    pf = projectFollowerDao.save(pf);
+                    project.getProjectFollowers().add(pf);
+                }
+                break;
+            }
+            case OPPONENT: {
+                final List<FinalSeminar> fsList = assureFinalSeminarAvailable(project);
+                //logger.debug("Assigning Opponent role to " + fsList.size() + " seminars for "+projectParticipant.person.id);
+                for (FinalSeminar fs : fsList) {
+                    if (userAlreadyAttachedAsParticipant(linkedUser, fs.getOppositions()))
+                        continue;
+                    FinalSeminarOpposition fsop = new FinalSeminarOpposition();
+                    final Student stud = roleDao.makeStudent(linkedUser);
+                    fsop.setOpponent(stud);
+                    fsop.setFinalSeminar(fs);
+                    fsop.setProject(project);
+                    fsop = finalSeminarOppositionDao.save(fsop);
+                    fs.getOppositions().add(fsop);
+                }
+                break;
+            }
+            case SUPERVISOR: {
+                //logger.debug("Assigning Supervisor role to "+projectParticipant.person.id);
+                final Member tmpMember = new Member(linkedUser, Member.Type.SUPERVISOR);
+                if (currentProjectMembers.contains(tmpMember)) {
+                    logger.debug("Skipping already assigned " + tmpMember.getType() + " user " + tmpMember.getUser());
+                    return;//Skip if already assigned	a supervisor role
+                }
+                logger.debug("Making '" + linkedUser + "' a supervisor");
+                final Employee emp = roleDao.makeEmployee(linkedUser);
+                project.setHeadSupervisor(emp);
+                break;
+            }
+            case CO_SUPERVISOR: {
+                ProjectFollower pf = new ProjectFollower();
+                //logger.debug("Assigning Co-supervisor role to "+projectParticipant.person.id);
+                final Member tmpMember = new Member(linkedUser, Member.Type.CO_SUPERVISOR);
+                if (currentProjectMembers.contains(tmpMember)) {
+                    logger.debug("Skipping already assigned " + tmpMember.getType() + " user " + tmpMember.getUser());
+                    return;//Skip if already assigned	a co-supervisor role
+                }
+                final Employee emp = roleDao.makeEmployee(linkedUser);
+                pf.setProjectRole(ProjectTeamMemberRoles.CO_SUPERVISOR);
+                pf.setFollower(emp);
+                //Add the assigned PF to the project and save
+                if (pf.getFollower() != null && pf.getProjectRole() != null) {
+                    pf.setProject(project);
+                    pf = projectFollowerDao.save(pf);
+                    project.getProjectFollowers().add(pf);
+                }
+                break;
+            }
+        }
+    }
+
+    /*
+      * Translate remote roles to local ones.
+      */
+    private LOCAL_PROJECT_ROLE extractLocalRole(final String fromRemoteRole) {
+        if (fromRemoteRole == null)
+            return null;
+        for (EXTERNAL_PROJECT_ROLE externalRole : EXTERNAL_PROJECT_ROLE.values()) {
+            if (fromRemoteRole.equalsIgnoreCase(externalRole.toString()))
+                return externalRole.toLocal();
+        }
+        return null;
+    }
+
+    private boolean userAlreadyAttachedAsParticipant(final User user, final List<? extends FinalSeminarParticipation> participantList) {
+        for (final FinalSeminarParticipation participant : participantList)
+            if (user.equals(participant.getUser()))
+                return true;
+        return false;
+    }
+
+    private List<FinalSeminar> assureFinalSeminarAvailable(final Project project) {
+        final List<FinalSeminar> fsList = finalSeminarDao.findFinalSeminarsByProject(project);
+        if (fsList.size() == 0) {
+            logger.warn("No seminars registered for the project " + project + ", creating a default seminar dated according to start/end dates for the project");
+            FinalSeminar fs = new FinalSeminar();
+            fs.setProject(project);
+            fs.setRoom("n/a");
+            fs.setStartDate(project.getDaisyStartDate());
+            fs.setEndDate(project.getDaisyStartDate());
+            fs = finalSeminarDao.save(fs);
+            fsList.add(fs);
+        }
+        return fsList;
+    }
+
+    private void userNameFromDTO(final Username username, final UsernameDTO usernameDTO) {
+        username.setUserName(usernameDTO.getUsername().toLowerCase().trim());
+        username.setRealm(usernameDTO.getRealm().toUpperCase().trim());
+    }
+
+    private UsernameDTO dtoFromUsername(final Username name) {
+        UsernameDTO dto = new UsernameDTO();
+        dto.setUsername(name.getUserName().toLowerCase().trim());
+        dto.setRealm(name.getRealm().toUpperCase().trim());
+        return dto;
+    }
+
+    private ProjectClass toLocalClass(final ProjectDTO projectDTO) {
+        ProjectClass pClass = null;
+        final String extractedType = extractProjectType(projectDTO);
+        pClass = projectClassDao.getProjectClass(extractedType);
+        return pClass;
+    }
+
+    private String extractProjectType(ProjectDTO projectDTO) {
+        String extractedType = ProjectClass.UNKNOWN;
+        if (projectDTO.type != null) {//Find class from project
+            extractedType = mapToLocalProjectClass(projectDTO.type);
+        } else {//Find class from participants as a fallback
+            for (ProjectParticipantDTO projectParticipant : projectDTO.participants) {
+                if (projectParticipant.level != null) {
+                    extractedType = mapToLocalProjectClass(projectParticipant.level);
+                    break;
+                }
+            }
+        }
+        logger.debug("Returning: " + extractedType + " as the extracted type of the project: " + projectDTO);
+        return extractedType;
+    }
+
+    private String mapToLocalProjectClass(final String input) {
+        if (input == null)
+            return null;
+        for (ProjectParticipantDTO.EXTERNAL_PROJECT_CLASS cls : ProjectParticipantDTO.EXTERNAL_PROJECT_CLASS.values()) {
+            if (input.equalsIgnoreCase(cls.toString()))
+                return cls.toLocal();
+        }
+        return null;
+    }
+
+    private ProjectStatus toLocalStatus(String externalProjectStatus) {
+        if (externalProjectStatus.equals("STARTED") || externalProjectStatus.equals("LATE")) {
+            return ProjectStatus.ACTIVE;
+        } else if (externalProjectStatus.equals("FINISHED")) {
+            return ProjectStatus.COMPLETED;
+        } else {
+            return ProjectStatus.INACTIVE;
+        }
+    }
+
+    @Transactional
+    public void addUnitToSupervisor(PersonDTO supervisorDTO, UnitDTO unitDTO) {
+        User supervisorUser = userDao.getUserByIdentifier(supervisorDTO.id);
+        Employee supervisor = supervisorDao.getFrom(supervisorUser);
+        if (supervisor != null) {
+            List<Keyword> currentUnits = supervisor.getKeywords().getFiltered(keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
+            //If supervisor is already assigned to a unit, remove to make sure only the latest unit is being added since we only allow one unit in Scipro.
+            //Supervisor is not going to be allowed to have more than one unit in the future, but some have two in Daisy at the moment.
+            if (!currentUnits.isEmpty()) {
+                logger.info(supervisor.getUser().getFullName() + " is already attached to a unit and this is being overwritten.");
+                supervisor.getKeywords().getAll().removeAll(currentUnits);
+            }
+            Keyword unitToAdd = keywordDao.getKeywordByIdentifierAndType(unitDTO.id, keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
+            logger.debug("Adding unit: " + unitToAdd.getKeyword() + " to supervisor: " + supervisor.getUser().getFullName());
+            supervisor.getKeywords().getAll().add(unitToAdd);
+        } else {
+            logger.debug("Can't find supervisor: " + supervisorDTO.id);
+        }
+    }
+
+    private void mergeLinkedResearchAreas(final User user, final Set<ResearchAreaDTO> areas) {
+        for (final ResearchAreaDTO researchAreaDTO : areas) {
+            Keyword area = keywordDao.getKeywordByIdentifierAndType(researchAreaDTO.id, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
+            if (area == null) {
+                logger.info("External research area: '" + researchAreaDTO + "' has no local representation, creating");
+                area = new Keyword(researchAreaDTO.name, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
+                area.setIdentifier(researchAreaDTO.id);
+                area = keywordDao.save(area);
+            } else {
+                logger.info("Research area " + area.getKeyword() + " already exists, skipping");
+            }
+            addResearchAreaToUser(user, area);
+        }
+    }
+
+    private void addResearchAreaToUser(User user, Keyword area) {
+        Employee supervisor = supervisorDao.getFrom(user);
+        logger.info("Adding research area: " + area.getKeyword() + " to supervisor " + supervisor.getUser().getFullName());
+        supervisor.getKeywords().getAll().add(area);
+    }
+
+    @Transactional
+    public void addUnexistingResearchAreas(final Set<ResearchAreaDTO> areas) {
+        final Set<Keyword> currentAreas = keywordDao.getKeywords(keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA), true);
+        final Set<ResearchAreaDTO> remoteAreas = new HashSet<ResearchAreaDTO>(areas);
+        final Set<Keyword> areasToRemove = new HashSet<Keyword>();
+        //Compare remote with database
+        for (Keyword currentArea : currentAreas) {
+            ResearchAreaDTO translatedArea = dtoFromAreaKeyword(currentArea);
+            if (!remoteAreas.contains(translatedArea)) {
+                logger.info("Area " + translatedArea.getName() + " does not exist on remote, preparing to remove.");
+                areasToRemove.add(currentArea);
+            }
+        }
+        //Delete areas that not exist on remote
+        for (Keyword areaToRemove : areasToRemove) {
+            keywordDao.delete(areaToRemove);
+            logger.debug("Deleted research area: " + areaToRemove.getKeyword() + " since it has been removed from remote system");
+        }
+        //Add areas to database
+        for (final ResearchAreaDTO researchAreaDTO : remoteAreas) {
+            Keyword area = keywordDao.getKeywordByIdentifierAndType(researchAreaDTO.id, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
+            if (area == null) {
+                logger.info("External research area: '" + researchAreaDTO + "' has no local representation, creating");
+                area = new Keyword(researchAreaDTO.name, keywordTypeDao.findByType(KeywordTypeDao.TYPE.RESEARCH_AREA));
+                area.setIdentifier(researchAreaDTO.id);
+                area = keywordDao.save(area);
+            } else if (!area.getKeyword().equals(researchAreaDTO.name)) {
+                logger.info("Research area " + area.getKeyword() + " has changed name, renaming to: " + researchAreaDTO.name);
+                area.setKeyword(researchAreaDTO.name);
+            } else {
+                logger.info("Research area " + area.getKeyword() + " already exists, skipping");
+            }
+            if (researchAreaDTO.active.equals("false")) {
+                logger.info(area.getKeyword() + " is inactivated on remote system.");
+                area.setDeleted(true);
+            }
+        }
+    }
+
+    @Transactional
+    public void addUnexistingUnitsAsUnits(final Set<UnitDTO> unitsFromDTO) {
+
+        final Set<Unit> currentUnits = unitService.findAllAsSet();
+        final Set<UnitDTO> remoteUnits = new HashSet<UnitDTO>(unitsFromDTO);
+
+        final Set<Unit> unitsToRemove = new HashSet<Unit>();
+        for (Unit unit : currentUnits) {
+            UnitDTO translatedUnit = dtoFromUnit(unit);
+            if (!remoteUnits.contains(translatedUnit)) {
+                logger.info("Unit " + translatedUnit.getName() + " does not exist on remote, preparing to remove.");
+                unitsToRemove.add(unit);
+            }
+        }
+        //Delete units that not exist on remote
+        for (Unit unitToRemove : unitsToRemove){
+            unitService.delete(unitToRemove.getId());
+            logger.debug("Deleted unit: " + unitToRemove.getTitle() + " since it has been removed from remote system");
+        }
+        //Add units to database
+        for (final UnitDTO unitDTO : remoteUnits) {
+            Unit unit = unitService.findByIdentifier(unitDTO.getId());
+            if (unit == null){
+                logger.info("External unit: '" + unitDTO + "' has no local representation, creating");
+                unit = new Unit();
+                unit.setIdentifier(unitDTO.getId());
+                unit.setTitle(unitDTO.getName());
+                unit = unitService.save(unit);
+            } else if (!unit.getTitle().equals(unitDTO.name)) {
+                logger.info("Unit " + unit.getTitle() + " has changed name, renaming to: " + unitDTO.name);
+                unit.setTitle(unitDTO.name);
+            }  else {
+                logger.info("Unit " + unit.getTitle() + " already exists, skipping");
+            }
+        }
+    }
+
+    public void removeUnitFromSupervisorsNotInSet(Set<PersonDTO> supervisorSet) {
+        final Set<Employee> supervisorsWithRemoteUnit = new HashSet<Employee>();
+        final Set<Employee> currentSupervisors = new HashSet<Employee>(supervisorDao.findAll());
+
+        //Create SciPro Employees from DTOs.
+        for (PersonDTO supervisorDTO : supervisorSet) {
+            User supervisorUser = userDao.getUserByIdentifier(supervisorDTO.id);
+            Employee supervisor = supervisorDao.getFrom(supervisorUser);
+            supervisorsWithRemoteUnit.add(supervisor);
+        }
+
+        //Remove units from supervisors that is not in the remote set.
+        for (Employee supervisor : currentSupervisors) {
+            if (!supervisorsWithRemoteUnit.contains(supervisor)) {
+                logger.debug(supervisor.getNameAsString() + " does not have a remote unit. Searching for local units to remove.");
+                List<Keyword> unitsToRemove = supervisor.getKeywords().getFiltered(keywordTypeDao.findByType(KeywordTypeDao.TYPE.UNIT));
+                if (!unitsToRemove.isEmpty()) {
+                    supervisor.getKeywords().getAll().removeAll(unitsToRemove);
+                    logger.debug("Removed units from: " + supervisor.getNameAsString());
+                }
+            }
+        }
+    }
+
+    private UnitDTO dtoFromUnitKeyword(final Keyword unit) {
+        UnitDTO dto = new UnitDTO();
+        dto.setName(unit.getKeyword());
+        if (unit.getIdentifier() != null)
+            dto.setId(unit.getIdentifier());
+        return dto;
+    }
+
+    private UnitDTO dtoFromUnit(final Unit unit) {
+        UnitDTO dto = new UnitDTO();
+        dto.setName(unit.getTitle());
+        if (unit.getIdentifier() != null)
+            dto.setId(unit.getIdentifier());
+        return dto;
+    }
+
+    private ResearchAreaDTO dtoFromAreaKeyword(final Keyword area) {
+        ResearchAreaDTO dto = new ResearchAreaDTO();
+        dto.setName(area.getKeyword());
+        if (area.getIdentifier() != null)
+            dto.setId(area.getIdentifier());
+        return dto;
+    }
 
 }
diff --git a/src/main/java/se/su/dsv/scipro/springdata/repos/UnitRepo.java b/src/main/java/se/su/dsv/scipro/springdata/repos/UnitRepo.java
index 7ba9656c99..0bf0a9722f 100644
--- a/src/main/java/se/su/dsv/scipro/springdata/repos/UnitRepo.java
+++ b/src/main/java/se/su/dsv/scipro/springdata/repos/UnitRepo.java
@@ -12,6 +12,6 @@ import se.su.dsv.scipro.data.dataobjects.Unit;
 @Transactional(readOnly = true)
 public interface UnitRepo extends JpaRepository<Unit, Long>, QueryDslPredicateExecutor<Unit> {
 
-    //nothing here yet
+    public Unit findByIdentifier(Long identifier);
 
 }
diff --git a/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UnitServiceImpl.java b/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UnitServiceImpl.java
index 9a6ba69ba1..25f33fb6fb 100644
--- a/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UnitServiceImpl.java
+++ b/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UnitServiceImpl.java
@@ -9,6 +9,8 @@ import se.su.dsv.scipro.springdata.repos.UnitRepo;
 import se.su.dsv.scipro.springdata.services.UnitService;
 
 import javax.annotation.Resource;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * @author: fred-fri
@@ -29,4 +31,13 @@ public class UnitServiceImpl extends AbstractQueryService<Unit, Long> implements
 		System.out.println("UnitServiceImpl instantiating...");
 	}
 
+    @Override
+    public Unit findByIdentifier(Long identifier) {
+        return unitRepo.findByIdentifier(identifier);
+    }
+
+    @Override
+    public Set<Unit> findAllAsSet() {
+        return new HashSet<Unit>(unitRepo.findAll());
+    }
 }
diff --git a/src/main/java/se/su/dsv/scipro/springdata/services/UnitService.java b/src/main/java/se/su/dsv/scipro/springdata/services/UnitService.java
index d6aa40fcad..3e50ed90df 100644
--- a/src/main/java/se/su/dsv/scipro/springdata/services/UnitService.java
+++ b/src/main/java/se/su/dsv/scipro/springdata/services/UnitService.java
@@ -2,12 +2,15 @@ package se.su.dsv.scipro.springdata.services;
 
 import se.su.dsv.scipro.data.dataobjects.Unit;
 
+import java.util.Set;
+
 /**
  * @author: fred-fri
  * date: 2012 03 26
  */
 public interface UnitService extends GenericService<Unit, Long>, QueryService<Unit, Long> {
 
-    //nothing here yet
+    public Unit findByIdentifier(Long identifier);
+    public Set<Unit> findAllAsSet();
 
 }