I attach my code according to Massimo Caprinali's request.
I welcome any code improvements. :)
/** All related parent items are closed during saving child work item */
public class StateChanger extends AbstractService implements IOperationParticipant {
// Using type id's form com.ibm.team.workitem.common plugin.xml (default for simple process)
private final static String CHILD_WORK_ITEM_TYPE_ID = "defect";
private final static String PARENT_WORK_ITEM_TYPE_ID = "task";
// Using workflow constants from eclipseWayWorkflow.xml (default for simple process)
private final static String PARENT_RESOLVING_WORKFLOW_ACTION_ID = "bugzillaWorkflow.action.resolve";
private final static String PARENT_CLOSING_WORKFLOW_ACTION_ID = "bugzillaWorkflow.action.close";
public void run(AdvisableOperation operation, IProcessConfigurationElement participantConfig, IParticipantInfoCollector collector, IProgressMonitor monitor) throws TeamRepositoryException {
// Preparation I.
ISaveParameter saveParam = (ISaveParameter) operation.getOperationData();
IWorkItem child = (IWorkItem) saveParam.getNewState();
// Types other than CHILD_WORK_ITEM_TYPE_ID are not interesting
if (!CHILD_WORK_ITEM_TYPE_ID.equals(child.getWorkItemType())) {
return;
}
// Preparation II.
ILinkService linkService = getService(ILinkService.class);
ILinkServiceLibrary linkLibrary = (ILinkServiceLibrary) linkService.getServiceLibrary(ILinkServiceLibrary.class);
// Listing and resolving links to 'related' work items
IItemReference workItemRef = IReferenceFactory.INSTANCE.createReferenceToItem(child);
ILinkQueryPage linkPage = linkLibrary.findLinks(WorkItemLinkTypes.RELATED_WORK_ITEM, workItemRef);
if (linkPage.getResultSize() == 0) {
addErrorInfo("Defect must have related work item!", "Add related work item before save!", collector);
return;
}
// Preparation III.
IRepositoryItemService repositoryItemService = getService(IRepositoryItemService.class);
IWorkItemServer workItemService = getService(IWorkItemServer.class);
IWorkItemCommon workItemCommon = getService(IWorkItemCommon.class);
// Processing links
ILinkCollection links = linkPage.getAllLinksFromHereOn();
for (ILink link : links) {
IReference otherRef = link.getOtherRef(workItemRef);
IWorkItemHandle parentHandle = (IWorkItemHandle) otherRef.resolve();
IWorkItem parent = (IWorkItem) repositoryItemService.fetchItem(parentHandle, null);
if(PARENT_WORK_ITEM_TYPE_ID.equals(parent.getWorkItemType()) && !isClosed(workItemCommon, parent)) { // process only items with type = PARENT_WORK_ITEM_TYPE_ID and open ones
// Changing to "resolved"
listWorkflowActions(workItemCommon, monitor, parent);
IWorkItem parentWorkingCopy = (IWorkItem) parent.getWorkingCopy();
workItemService.saveWorkItem2(parentWorkingCopy, null, PARENT_RESOLVING_WORKFLOW_ACTION_ID);
// Changing to "closed"
parent = (IWorkItem) repositoryItemService.fetchItem(parentHandle, null);
listWorkflowActions(workItemCommon, monitor, parent);
parentWorkingCopy = (IWorkItem) parent.getWorkingCopy();
workItemService.saveWorkItem2(parentWorkingCopy, null, PARENT_CLOSING_WORKFLOW_ACTION_ID);
// ! Two-phase saving should not be needed for well customized workflow
}
}
}
private static void addErrorInfo(String summary, String description, IParticipantInfoCollector collector) {
if (collector != null) {
IReportInfo info = collector.createInfo(summary, description);
info.setSeverity(IProcessReport.ERROR);
collector.addInfo(info);
}
}
private boolean isClosed(IWorkItemCommon workItemCommon, IWorkItem workItem) {
if (workItem != null) {
Identifier<IState> state= workItem.getState2();
if (state != null) {
try {
IWorkflowInfo workflowInfo= workItemCommon.findWorkflowInfo(workItem, null);
if (workflowInfo.stateGroupContains(IWorkflowInfo.CLOSED_STATES, state))
return true;
} catch (TeamRepositoryException e) {
return false;
}
}
}
return false;
}
}