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
*
* - name
*
- summary (can be empty but not null)
*
- description (can be empty but not null)
*
- members (can be empty but not null)
*
- processTemplate
*
*
* @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;
}
}