Restrict parent-child links between work items?
Accepted answer
I implemented something very similar to this in our environment. We had a certain usage model for how we expected work items to be linked to one another in a plan. If users didn't conform to this usage model, our earned value reports wouldn't display correctly. To try and teach people the correct usage model, we implemented a precondition that throws warnings (not errors) if a user violates the expected link relationships. Here's my code:
package com.smxg.opex.clm;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import com.ibm.team.links.common.IReference;
import com.ibm.team.process.common.IProcessConfigurationElement;
import com.ibm.team.process.common.advice.AdvisableOperation;
import com.ibm.team.process.common.advice.IAdvisorInfo;
import com.ibm.team.process.common.advice.IAdvisorInfoCollector;
import com.ibm.team.process.common.advice.runtime.IOperationAdvisor;
import com.ibm.team.repository.common.IAuditable;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.repository.service.AbstractService;
import com.ibm.team.workitem.common.IAuditableCommon;
import com.ibm.team.workitem.common.ISaveParameter;
import com.ibm.team.workitem.common.internal.workflow.WorkflowManager;
import com.ibm.team.workitem.common.model.IWorkItem;
import com.ibm.team.workitem.common.model.IWorkItemHandle;
import com.ibm.team.workitem.common.model.WorkItemEndPoints;
import com.ibm.team.workitem.common.workflow.IWorkflowInfo;
import com.ibm.team.workitem.service.IWorkItemServer;
public class EnforceEarnedValueUsageModel extends AbstractService implements IOperationAdvisor
{
boolean Debug = false;
@Override
public void run(AdvisableOperation operation, IProcessConfigurationElement advisorConfiguration, IAdvisorInfoCollector collector, IProgressMonitor monitor) throws TeamRepositoryException
{
if(advisorConfiguration.getAttribute("description") != null) Debug = advisorConfiguration.getAttribute("description").contains("DEBUG");
if(Debug) System.out.println("EnforceEarnedValueUsageModel advisor has been triggered.");
Object data = operation.getOperationData();
if (!(data instanceof ISaveParameter)) return;
ISaveParameter saveParameter = (ISaveParameter) data;
IAuditable auditable = saveParameter.getNewState();
if(!(auditable instanceof IWorkItem)) return;
IAuditableCommon iac = saveParameter.getSaveOperationParameter().getAuditableCommon();
IWorkItem workItem = (IWorkItem) auditable;
//If there is no parent work item, we don't need to worry about any further validating. We can just exit.
List<IReference> ParentReferenceList;
if(saveParameter.getNewReferences().hasReferences(WorkItemEndPoints.PARENT_WORK_ITEM)) {
ParentReferenceList = (ArrayList<IReference>) saveParameter.getNewReferences().getReferences(WorkItemEndPoints.PARENT_WORK_ITEM);
} else {
if(Debug) System.out.println("There is no parent work item. No rules will be verified.");
return;
}
//We're only interested in validating a few types of work items: Task, Task with Approval, Sub Task, Plan Item, Change Request
String WI_TypeID = workItem.getWorkItemType();
if(Debug) System.out.println("The work item type is: " + WI_TypeID);
if(!WI_TypeID.equals("omr.309.mat.workitem.workItemType.plan_item") && !WI_TypeID.equals("omr.309.mat.workItemType.sub_task") && !WI_TypeID.equals("task") && !WI_TypeID.equals("omr.309.mat.workItemType.task_with_approval") && !WI_TypeID.equals("omr.309.mat.workItemType.change_request")) {
if(Debug) System.out.println("No rules are verified for this work item type.");
return;
}
//Let's figure out what this work item's parent is.
IReference ParentRef = ParentReferenceList.get(0);
IWorkItem ParentWI = iac.resolveAuditable((IWorkItemHandle)ParentRef.resolve(),IWorkItem.FULL_PROFILE, null);
String ParentTypeID = ParentWI.getWorkItemType();
//Verify that plan items (Change Request, and Plan Item) are not children of execution items
if(WI_TypeID.equals("omr.309.mat.workitem.workItemType.plan_item") || WI_TypeID.equals("omr.309.mat.workItemType.change_request")) {
if(!ParentTypeID.equals("omr.309.mat.workitem.workItemType.plan_item") && !ParentTypeID.equals("omr.309.mat.workItemType.change_request")) {
IAdvisorInfo createProblemInfo = collector.createProblemInfo("Plan Items Must Be Children of Other Plan Items", "The work item you are trying to save is a type of \"plan item\", but the parent of this work item is an \"execution item\". Plan items should only be children of other plan items to ensure complexity roll-up functions correctly.", "error");
collector.addInfo(createProblemInfo);
return;
}
}
//Check that the user isn't trying to save a Task as a child of another Task.
if(WI_TypeID.equals("task") || WI_TypeID.equals("omr.309.mat.workItemType.task_with_approval")) {
if(ParentTypeID.equals("task") || ParentTypeID.equals("omr.309.mat.workItemType.task_with_approval")) {
IAdvisorInfo createProblemInfo = collector.createProblemInfo("Tasks Must Not Be Children of Other Tasks", "The earned value usage model, which must be adhered to for the CLM Earned Value report to work correctly, stipulates that Tasks cannot be children of other Tasks. Change the parent work item to a Plan Item and try again.", "error");
collector.addInfo(createProblemInfo);
return;
}
}
//Check whether the user is trying to save a Sub Task below another Sub Task.
if(WI_TypeID.equals("omr.309.mat.workItemType.sub_task") && ParentTypeID.equals("omr.309.mat.workItemType.sub_task")) {
IAdvisorInfo createProblemInfo = collector.createProblemInfo("Sub Tasks Must Not be Children of Other Sub Tasks", "The earned value usage model, which must be adhered to for the CLM Earned Value report to work correctly, stipulates that Sub Tasks cannot be children of other Sub Tasks. Change the parent work item to a Task and try again.", "error");
collector.addInfo(createProblemInfo);
return;
}
if(WI_TypeID.equals("omr.309.mat.workItemType.sub_task") && (ParentTypeID.equals("omr.309.mat.workitem.workItemType.plan_item") || ParentTypeID.equals("omr.309.mat.workItemType.change_request"))) {
IAdvisorInfo createProblemInfo = collector.createProblemInfo("Sub Tasks Must Not be Children of Planning Items", "The earned value usage model, which must be adhered to for the CLM Earned Value report to work correctly, stipulates that Sub Tasks cannot be direct children of Planning work item types. Use a Task work item type instead.", "error");
collector.addInfo(createProblemInfo);
return;
}
}
}
One other answer
Start here to find out about extending RTC: https://rsjazz.wordpress.com/2015/09/30/learning-to-fly-getting-started-with-the-rtc-java-apis/
Comments
Jorge Gabriel Pereira
Mar 14 '16, 4:06 p.m.Ralph and Nate, tks a lot.