package cz.muni.fi.rtc.teacherWorkbench.importer;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.osgi.util.NLS;

import com.ibm.team.process.client.IClientProcess;
import com.ibm.team.process.client.IProcessItemService;
import com.ibm.team.process.client.workingcopies.IProcessAreaWorkingCopy;
import com.ibm.team.process.client.workingcopies.IProjectAreaWorkingCopy;
import com.ibm.team.process.client.workingcopies.ITeamWorkingCopy;
import com.ibm.team.process.common.IDescription;
import com.ibm.team.process.common.IProcessDefinition;
import com.ibm.team.process.common.IProjectArea;
import com.ibm.team.process.common.IRole;
import com.ibm.team.process.common.ITeamArea;
import com.ibm.team.process.common.ITeamAreaHandle;
import com.ibm.team.process.common.ITeamAreaHierarchy;
import com.ibm.team.process.internal.client.ProcessClientService;
import com.ibm.team.repository.client.IContributorManager;
import com.ibm.team.repository.client.IItemManager;
import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.common.IContributor;
import com.ibm.team.repository.common.IContributorHandle;
import com.ibm.team.repository.common.TeamRepositoryException;

import cz.muni.fi.rtc.teacherWorkbench.importer.exceptions.ImporterException;
import cz.muni.fi.rtc.teacherWorkbench.model.ImportedPerson;
import cz.muni.fi.rtc.teacherWorkbench.model.Project;

/**
 * Used for importing projects {@link Project} to RTC
 * @author Jan Stastny
 *
 */
public class ProjectImporter {

	private ImporterConfiguration configuration;
	
	private ITeamRepository repo;
	
	private IProgressMonitor monitor = LogProgressMonitor.getInstance();
	
	private Log log = LogFactory
		.getLog(cz.muni.fi.rtc.teacherWorkbench.importer.ProjectImporter.class);

	/**
	 * Constructor.
	 * @param conf Configuration
	 * @throws ImporterException if the configuration misses some mandatory fields
	 */
	public ProjectImporter(ImporterConfiguration conf) throws ImporterException {
		this.configuration = conf;
		init();
	}
	
	private void init() throws ImporterException {
		this.repo = Utils.establishRepositoryConnection(configuration);
	}
	
	
	
	/**
	 * Imports the given projects to the RTC repository
	 * 
* Exceptions thrown during creation of the projects are logged under the level error and are not thrown *
* Invitation is sent to the users only if they are not in the root category * (root category users are meant to be teachers and therefore we don't send * the invitations to them) *
* Mandatory fields of each project * * * @param projects Projects to add * @throws ImporterException If some of the mandatory fields are not filled. * It fails atomically in this case -- no changes written to RTC. */ public void importProjects(Collection projects) throws ImporterException { // Check the mandatory fields for(Project p: projects) { if(p.getName() == null || p.getName().equals("")) { throw new ImporterException("name not set in " + p, new IllegalArgumentException(p.toString())); } if(p.getSummary() == null) { throw new ImporterException("Summary null in " + p, new IllegalArgumentException(p.toString())); } if(p.getDescrition() == null) { throw new ImporterException("Description null in " + p, new IllegalArgumentException(p.toString())); } if(p.getMembers() == null) { throw new ImporterException("Members null in " + p, new IllegalArgumentException(p.toString())); } if(p.getProcessTemplate() == null || p.getProcessTemplate().equals("")) { throw new ImporterException("Process template not set in " + p, new IllegalArgumentException(p.toString())); } } if(repo == null) { throw new ImporterException("Repository connection is null"); } for(Project p: projects) { log.info("Started creating project " + p.getName()); try { IProcessItemService service= (IProcessItemService) repo.getClientLibrary(IProcessItemService.class); ProcessClientService serviceProcess = (ProcessClientService) repo.getClientLibrary(IProcessItemService.class); IContributorManager conManager = repo.contributorManager(); IProcessDefinition process = service.findProcessDefinition(p.getProcessTemplate(), IProcessItemService.ALL_PROPERTIES, null); if(process == null) { log.error("Process template named " + p.getProcessTemplate() + " not found"); } IProjectArea area = service.createProjectArea(); area.setName(p.getName()); area.setProcessDefinition(process); IDescription description = area.getDescription(); description.setSummary(p.getSummary()); area = (IProjectArea) service.save(area, monitor); service.initialize(area, null); Map roles = fetchRoles(service, area); // Add root members (teachers) IProjectAreaWorkingCopy areaWc = (IProjectAreaWorkingCopy) service.getWorkingCopyManager().createPrivateWorkingCopy(area); ITeamWorkingCopy rootTeamWc = areaWc.getTeam(); ITeamAreaHierarchy hi = area.getTeamAreaHierarchy(); Set roots = hi.getRoots(); // Assume that the initialized project area has (at least) one project area and put // all the members to it ITeamAreaHandle teamAreaHandle = (ITeamAreaHandle) roots.iterator().next(); ITeamArea teamArea = (ITeamArea) repo.itemManager().fetchCompleteItem(teamAreaHandle, IItemManager.DEFAULT, monitor); IProcessAreaWorkingCopy teamWc = (IProcessAreaWorkingCopy)service.getWorkingCopyManager().createPrivateWorkingCopy(teamArea); List contributors = new ArrayList(); ITeamWorkingCopy teamAreaWc = teamWc.getTeam(); for(ImportedPerson person : p.getMembers()) { ITeamWorkingCopy work; IContributor contributor = conManager.fetchContributorByUserId(person.getUID(), monitor); if (!p.isInRoot(person)) { work = teamAreaWc; contributors.add(contributor); } else { work = rootTeamWc; } work.addContributors(new IContributor[] {contributor}); for(String roleId : p.getUserRoles(person)) { work.setRoleCast(contributor, new IRole[] {roles.get(roleId)}); } } String projectAreaName; try { projectAreaName = URLEncoder.encode(area.getName(), "UTF-8").replaceAll("\\+", "%20"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } catch (UnsupportedEncodingException e) { // UTF-8 should always be supported, but just in case... projectAreaName = area.getName(); log.error(e); } String projectWebURL = NLS.bind("{0}web/projects/{1}", repo.getRepositoryURI(), projectAreaName); //$NON-NLS-1$ serviceProcess.generateTeamInvitation( "RTC Team Invitation", "Hello,\nyou were added to the project " + p.getName() +".\n" + "Project can be accessed online at " + projectWebURL + "\n\n" + "Use the invitation bellow to connect from Eclipse client\n\n", "", contributors.toArray(new IContributorHandle[]{}), area, monitor); teamWc.save(null); areaWc.save(null); log.info("Project created " + p.getName()); } catch (TeamRepositoryException e) { log.error("Operation failed", e); } } } private Map fetchRoles(IProcessItemService service, IProjectArea area) throws TeamRepositoryException { // Fetch all the available roles in the project area IClientProcess clientProcess = service.getClientProcess(area, monitor); IRole[] allRoles = clientProcess.getRoles(area, monitor); // Map mapping role ids used in project to IRole Map roleMap = new HashMap(); for(IRole role : allRoles) { roleMap.put(role.getId(), role); } return roleMap; } }