How to fetch workitem Approvals through Jazz API
Hi,
I developed a java client to retrieve a workitem base on several criteria.
Now I tried to retrieve the Approvals associated with this workitem and retrieve the Reviewer/submitter of the Approvals:
IApprovals approvals = searchWorkItem.getApprovals();
java.util.List<IApproval> approval = approvals.getContents() ;
From the JavaDoc the object com.ibm.team.workitem.common.model.IApprovals has the following method:
IContributorHandle getApprover() -> Returns the contributor that is asked for approval.
IApprovalDescriptor getDescriptor() -> Returns the approval descriptor this approval belongs to.
I tried to retrieve both IContributorHandle and IApprovalDescriptor objects but have no luck here.
Could someone please help here?
Thanks.
I developed a java client to retrieve a workitem base on several criteria.
Now I tried to retrieve the Approvals associated with this workitem and retrieve the Reviewer/submitter of the Approvals:
IApprovals approvals = searchWorkItem.getApprovals();
java.util.List<IApproval> approval = approvals.getContents() ;
From the JavaDoc the object com.ibm.team.workitem.common.model.IApprovals has the following method:
IContributorHandle getApprover() -> Returns the contributor that is asked for approval.
IApprovalDescriptor getDescriptor() -> Returns the approval descriptor this approval belongs to.
I tried to retrieve both IContributorHandle and IApprovalDescriptor objects but have no luck here.
Could someone please help here?
Thanks.
13 answers
Kelvin and I sorted this out over chat (and I asked that API usage questions be posted in the Extending RTC forum).
Need to use ITeamRepository.itemManager() to get the IItemManager, and use its fetch methods to fetch the contributor items, given the contributor handles.
One potential gotcha to be aware of with the IItemManager fetch methods. The single-item fetch methods throw an exception (ItemNotFoundException) if the item no longer exists (or can't be seen by the user). The multi-fetch methods return null in the resulting list, so need to check for that. The safer one to use is com.ibm.team.repository.client.IItemManager.fetchCompleteItemsPermissionAware(List, int, IProgressMonitor), since the resulting fetch result object has them partitioned into fetched, missing, and permission denied, so avoids the risk of nulls.
Need to use ITeamRepository.itemManager() to get the IItemManager, and use its fetch methods to fetch the contributor items, given the contributor handles.
One potential gotcha to be aware of with the IItemManager fetch methods. The single-item fetch methods throw an exception (ItemNotFoundException) if the item no longer exists (or can't be seen by the user). The multi-fetch methods return null in the resulting list, so need to check for that. The safer one to use is com.ibm.team.repository.client.IItemManager.fetchCompleteItemsPermissionAware(List, int, IProgressMonitor), since the resulting fetch result object has them partitioned into fetched, missing, and permission denied, so avoids the risk of nulls.
Nick,
I looked up on Java Doc IItemManager.fetchCompleteItemsPermissionAware requires three parameters:
IFetchResult fetchCompleteItemsPermissionAware(java.util.List itemHandles,
int flags,
IProgressMonitor monitor)
I have the following question:
1. Do you refer itemHandles as IContributorHandle that I retrieved from method IApproval.getApprover()?
IApprovals approvals = searchWorkItem.getApprovals();
java.util.List<IApproval> approval = approvals.getContents() ;
IApproval temp = approval.get(0);
IContributorHandle contributorimpl = temp.getApprover();
2. Any recommended value for the flags parameters? - here is the description from JavaDoc: bit-wise OR of the constants declared on this interface; specify (@link #DEFAULT IItemManager.DEFAULT} to get a shared item (recommended) that tracks the current state of the item; specify (@link #REFRESH IItemManager.REFRESH} to ensure that the shared item is up-to-date; specify (@link #UNSHARED IItemManager.UNSHARED} to return the current state of the item not as a shared item (and without affecting the shared item if one exists)
3. IItemManager.fetchCompleteItemsPermissionAware returns IFetchResult (List). I assume to call the method IFetchResult.getRetrievedItems() to get the object com.ibm.team.repository.common.model.impl.ContributorImpl
and thus getting the approver's name.
Please correct me if my understanding is incorrect.
Thanks.
I looked up on Java Doc IItemManager.fetchCompleteItemsPermissionAware requires three parameters:
IFetchResult fetchCompleteItemsPermissionAware(java.util.List itemHandles,
int flags,
IProgressMonitor monitor)
I have the following question:
1. Do you refer itemHandles as IContributorHandle that I retrieved from method IApproval.getApprover()?
IApprovals approvals = searchWorkItem.getApprovals();
java.util.List<IApproval> approval = approvals.getContents() ;
IApproval temp = approval.get(0);
IContributorHandle contributorimpl = temp.getApprover();
2. Any recommended value for the flags parameters? - here is the description from JavaDoc: bit-wise OR of the constants declared on this interface; specify (@link #DEFAULT IItemManager.DEFAULT} to get a shared item (recommended) that tracks the current state of the item; specify (@link #REFRESH IItemManager.REFRESH} to ensure that the shared item is up-to-date; specify (@link #UNSHARED IItemManager.UNSHARED} to return the current state of the item not as a shared item (and without affecting the shared item if one exists)
3. IItemManager.fetchCompleteItemsPermissionAware returns IFetchResult (List). I assume to call the method IFetchResult.getRetrievedItems() to get the object com.ibm.team.repository.common.model.impl.ContributorImpl
and thus getting the approver's name.
Please correct me if my understanding is incorrect.
Thanks.
Hi Kelvin, yes that's all correct.
You also probably want to iterate over all the approvals and collect all the contributor handles, and fetch them all in one call to fetchCompleteItemsPermissionAware, to reduce the number of round trips to the server.
This is a very common pattern in Jazz:
- get an IXYZHandle (or array or list of them) from somewhere
- collect as many of these as you're dealing with at the time, to reduce round trips to the server and/or database
- fetch the items using one of the IItemManager (client-side) or IRepositoryItemService (server-side) methods
- it returns the fetched IXYZ items
You also probably want to iterate over all the approvals and collect all the contributor handles, and fetch them all in one call to fetchCompleteItemsPermissionAware, to reduce the number of round trips to the server.
This is a very common pattern in Jazz:
- get an IXYZHandle (or array or list of them) from somewhere
- collect as many of these as you're dealing with at the time, to reduce round trips to the server and/or database
- fetch the items using one of the IItemManager (client-side) or IRepositoryItemService (server-side) methods
- it returns the fetched IXYZ items
Hi Nick,
I tried the following code. I think itemManager.fetchCompleteItemsPermissionAware returns the list.
And looks like IFetchResult.getRetrievedItems() also returns a list.
When I tried to retrieve an object for the List and cast it to object com.ibm.team.repository.common.model.impl.ContributorImpl, I got the follow exception:
Exception in thread "main" java.lang.ClassCastException: $Proxy10 incompatible with com.ibm.team.repository.common.model.impl.ContributorImpl
at com.ibm.websphere.rtc.workItem.RTCManager.getWorkItemNumberFromAPARNumber(RTCManager.java:464)
at com.ibm.websphere.rtc.workItem.RTCManager.queryDefectbyAPARNumber(RTCManager.java:493)
at com.ibm.websphere.rtc.workItem.TestClass_RTCManager.queryDefect(TestClass_RTCManager.java:36)
at com.ibm.websphere.rtc.workItem.TestClass_RTCManager.main(TestClass_RTCManager.java:60)
Could you please shed some light here? Thanks.
Here is the code snippet:
List <IContributorHandle> temp21 = new ArrayList<IContributorHandle>();
for (int i=0; i < approval.size(); i++){
IApproval temp = approval.get(i);
IContributorHandle contributorimpl = temp.getApprover();
System.out.println ("contributorimpl: " + contributorimpl.toString());
temp21.add(0, contributorimpl);
}
IItemManager itemManager = teamRepository.itemManager();
IFetchResult temp100 = itemManager.fetchCompleteItemsPermissionAware(temp21, 0, monitor);
List <com> temp200 = null;
temp200 = temp100.getRetrievedItems();
if (temp200!=null){
System.out.println ("temp200 is not null");
for (int i=0; i < temp200.size(); i++){
com.ibm.team.repository.common.model.impl.ContributorImpl _contributorimpl = (com.ibm.team.repository.common.model.impl.ContributorImpl) temp200.get(i);
System.out.println("_contributorimpl: "+ _contributorimpl.getEmailAddress());
}
}else {
System.out.println ("temp200 is null");
}
I tried the following code. I think itemManager.fetchCompleteItemsPermissionAware returns the list.
And looks like IFetchResult.getRetrievedItems() also returns a list.
When I tried to retrieve an object for the List and cast it to object com.ibm.team.repository.common.model.impl.ContributorImpl, I got the follow exception:
Exception in thread "main" java.lang.ClassCastException: $Proxy10 incompatible with com.ibm.team.repository.common.model.impl.ContributorImpl
at com.ibm.websphere.rtc.workItem.RTCManager.getWorkItemNumberFromAPARNumber(RTCManager.java:464)
at com.ibm.websphere.rtc.workItem.RTCManager.queryDefectbyAPARNumber(RTCManager.java:493)
at com.ibm.websphere.rtc.workItem.TestClass_RTCManager.queryDefect(TestClass_RTCManager.java:36)
at com.ibm.websphere.rtc.workItem.TestClass_RTCManager.main(TestClass_RTCManager.java:60)
Could you please shed some light here? Thanks.
Here is the code snippet:
List <IContributorHandle> temp21 = new ArrayList<IContributorHandle>();
for (int i=0; i < approval.size(); i++){
IApproval temp = approval.get(i);
IContributorHandle contributorimpl = temp.getApprover();
System.out.println ("contributorimpl: " + contributorimpl.toString());
temp21.add(0, contributorimpl);
}
IItemManager itemManager = teamRepository.itemManager();
IFetchResult temp100 = itemManager.fetchCompleteItemsPermissionAware(temp21, 0, monitor);
List <com> temp200 = null;
temp200 = temp100.getRetrievedItems();
if (temp200!=null){
System.out.println ("temp200 is not null");
for (int i=0; i < temp200.size(); i++){
com.ibm.team.repository.common.model.impl.ContributorImpl _contributorimpl = (com.ibm.team.repository.common.model.impl.ContributorImpl) temp200.get(i);
System.out.println("_contributorimpl: "+ _contributorimpl.getEmailAddress());
}
}else {
System.out.println ("temp200 is null");
}
The pattern in Jazz/RTC programming for fetching items is:
- get an IXYZHandle object
- fetch it, usually via IItemManager.fetch*
- get the items from the result and cast them to IXYZ
Here, you're casting down to XYZImpl, which is casting down too far.
Try casting down to IContributor (fully qualified name: com.ibm.team.repository.common.IContributor) instead.
The reason it's failing is because, although the underlying concrete item class is ContributorImpl, the item is wrapped in a dynamic proxy that implements IContributor but does not implement or extend ContributorImpl.
In general, if you're referring to types with 'internal' in the package name, that's a sign that you've strayed away from the public API.
- get an IXYZHandle object
- fetch it, usually via IItemManager.fetch*
- get the items from the result and cast them to IXYZ
Here, you're casting down to XYZImpl, which is casting down too far.
Try casting down to IContributor (fully qualified name: com.ibm.team.repository.common.IContributor) instead.
The reason it's failing is because, although the underlying concrete item class is ContributorImpl, the item is wrapped in a dynamic proxy that implements IContributor but does not implement or extend ContributorImpl.
In general, if you're referring to types with 'internal' in the package name, that's a sign that you've strayed away from the public API.
Hi Kelvin,
Child/related work items are represented as links. See the methods on com.ibm.team.links.client.ILinkManager and search the forums for examples (actually, API questions like this should really go in the Extending Team Concert forum).
For getting a summary of the contents of a change set, you can fetch the IChangeSet items from the IChangeSetHandle handles using the pattern above, which will let you list the individual IChange's to items in the change set. These only carry the simple item name, though, not the path. To get the paths, you need to use com.ibm.team.filesystem.client.IFileSystemView.interpretChanges(List, IProgressMonitor) to get the corresponding IChangeSetSummary's.
See https://jazz.net/forums/viewtopic.php?t=21533 for details.
Child/related work items are represented as links. See the methods on com.ibm.team.links.client.ILinkManager and search the forums for examples (actually, API questions like this should really go in the Extending Team Concert forum).
For getting a summary of the contents of a change set, you can fetch the IChangeSet items from the IChangeSetHandle handles using the pattern above, which will let you list the individual IChange's to items in the change set. These only carry the simple item name, though, not the path. To get the paths, you need to use com.ibm.team.filesystem.client.IFileSystemView.interpretChanges(List, IProgressMonitor) to get the corresponding IChangeSetSummary's.
See https://jazz.net/forums/viewtopic.php?t=21533 for details.
Nick, thanks.
I searched on the forum by using the key term "ILinkManager". There are 16 docs returned and most of them referring on "creating the new link".
There is one doc to show how to retrieve change set assoicated to work item:
https://jazz.net/forums/viewtopic.php?t=839&highlight=ilinkmanager&sid=c47e9624773867c04d37488bd6b457c5
From the doc:
ILinkManager linkManager = (ILinkManager) repository.getClientLibrary(ILinkManager.class);
IReferenceFactory referenceFactory = linkManager.referenceFactory();
IReference workItemReference = referenceFactory.createReferenceToItem(workItem.getItemHandle());
//Find all ILinks which attach a change set to the work item.
ILinkQueryPage linkQueryPage = null;
try {
linkQueryPage = linkManager.findLinksByTarget("com.ibm.team.filesystem.workitems.change_set", workItemReference, monitor);
} catch (TeamRepositoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ILinkCollection linkCollection = linkQueryPage.getAllLinksFromHereOn();
//Put the ILinks in a list.
List<ILink> linksById = (List<ILink>)linkCollection.getLinksById("com.ibm.team.filesystem.workitems.change_set");
List<ILink> changeSetLinks = linksById;
System.out.println("********************"+ linksById.size()); //ALWAYS getting size 0
List<IReference> changeSetReferences = new ArrayList<IReference>();
for (ILink link : changeSetLinks) {
IChangeSetHandle changeSetHandle = (IChangeSetHandle)link.getSourceRef().resolve();
ItemId<IChangeSet> changeSetItemId = ChangeSetUtil.getChangeSet(changeSetHandle);
From the java doc the method findLinksByTarget can look up any link type associated with the workitem (link to change-set or link to other workitem).
I assume the same code snippet above can retrieve the link to other workitem to identify the Link type and id. For example:
"com.ibm.team.filesystem.workitems.change_set"
If my assumption is correct what would be the link type name, which returns the ILink objects.
According to the same forum page would it be one of the following type.
Could you please confirm if my understanding is correct or not?
Thanks.
public static final String RELATED_WORK_ITEM= "com.ibm.team.workitem.linktype.relatedworkitem"; //$NON-NLS-1$
public static final String DUPLICATE_WORK_ITEM= "com.ibm.team.workitem.linktype.duplicateworkitem"; //$NON-NLS-1$
public static final String COPIED_WORK_ITEM= "com.ibm.team.workitem.linktype.copiedworkitem"; //$NON-NLS-1$
public static final String RELATED_ARTIFACT= "com.ibm.team.workitem.linktype.relatedartifact"; //$NON-NLS-1$
public static final String ATTACHMENT= "com.ibm.team.workitem.linktype.attachment"; //$NON-NLS-1$
public static final String BLOCKS_WORK_ITEM= "com.ibm.team.workitem.linktype.blocksworkitem"; //$NON-NLS-1$
public static final String PARENT_WORK_ITEM= "com.ibm.team.workitem.linktype.parentworkitem"; //$NON-NLS-1$
I searched on the forum by using the key term "ILinkManager". There are 16 docs returned and most of them referring on "creating the new link".
There is one doc to show how to retrieve change set assoicated to work item:
https://jazz.net/forums/viewtopic.php?t=839&highlight=ilinkmanager&sid=c47e9624773867c04d37488bd6b457c5
From the doc:
ILinkManager linkManager = (ILinkManager) repository.getClientLibrary(ILinkManager.class);
IReferenceFactory referenceFactory = linkManager.referenceFactory();
IReference workItemReference = referenceFactory.createReferenceToItem(workItem.getItemHandle());
//Find all ILinks which attach a change set to the work item.
ILinkQueryPage linkQueryPage = null;
try {
linkQueryPage = linkManager.findLinksByTarget("com.ibm.team.filesystem.workitems.change_set", workItemReference, monitor);
} catch (TeamRepositoryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ILinkCollection linkCollection = linkQueryPage.getAllLinksFromHereOn();
//Put the ILinks in a list.
List<ILink> linksById = (List<ILink>)linkCollection.getLinksById("com.ibm.team.filesystem.workitems.change_set");
List<ILink> changeSetLinks = linksById;
System.out.println("********************"+ linksById.size()); //ALWAYS getting size 0
List<IReference> changeSetReferences = new ArrayList<IReference>();
for (ILink link : changeSetLinks) {
IChangeSetHandle changeSetHandle = (IChangeSetHandle)link.getSourceRef().resolve();
ItemId<IChangeSet> changeSetItemId = ChangeSetUtil.getChangeSet(changeSetHandle);
From the java doc the method findLinksByTarget can look up any link type associated with the workitem (link to change-set or link to other workitem).
I assume the same code snippet above can retrieve the link to other workitem to identify the Link type and id. For example:
"com.ibm.team.filesystem.workitems.change_set"
If my assumption is correct what would be the link type name, which returns the ILink objects.
According to the same forum page would it be one of the following type.
Could you please confirm if my understanding is correct or not?
Thanks.
public static final String RELATED_WORK_ITEM= "com.ibm.team.workitem.linktype.relatedworkitem"; //$NON-NLS-1$
public static final String DUPLICATE_WORK_ITEM= "com.ibm.team.workitem.linktype.duplicateworkitem"; //$NON-NLS-1$
public static final String COPIED_WORK_ITEM= "com.ibm.team.workitem.linktype.copiedworkitem"; //$NON-NLS-1$
public static final String RELATED_ARTIFACT= "com.ibm.team.workitem.linktype.relatedartifact"; //$NON-NLS-1$
public static final String ATTACHMENT= "com.ibm.team.workitem.linktype.attachment"; //$NON-NLS-1$
public static final String BLOCKS_WORK_ITEM= "com.ibm.team.workitem.linktype.blocksworkitem"; //$NON-NLS-1$
public static final String PARENT_WORK_ITEM= "com.ibm.team.workitem.linktype.parentworkitem"; //$NON-NLS-1$
I'm not sure I understand the question:
> If my assumption is correct what would be the link type name, which returns the ILink objects.
The ILinkManager.find* methods can be used to find any kind of links between two items. ILink is the type of object returned in all cases. An ILink represents a link between a source reference and a target reference, where a reference (IReference) may be either an item reference (item handle) to an item in the same repostiory, or an URI reference (arbitrary URL, sometimes used to refer to items in other repositories).
In the case of the "com.ibm.team.filesystem.workitems.change_set" link type id, the source reference is a change set handle (IChangeSetHandle) and the target is a work item handle (IWorkItemHandle).
To search for change sets associated with a given work item, you'd use findLinksByTarget. To search for work items associated with a given change set, you'd use findLinksBySource.
To get the resulting item handles from the ILinks in the result, use:
Then cast the itemHandle down to IChangeSetHandle or IWorkItemHandle as appropriate.
> If my assumption is correct what would be the link type name, which returns the ILink objects.
The ILinkManager.find* methods can be used to find any kind of links between two items. ILink is the type of object returned in all cases. An ILink represents a link between a source reference and a target reference, where a reference (IReference) may be either an item reference (item handle) to an item in the same repostiory, or an URI reference (arbitrary URL, sometimes used to refer to items in other repositories).
In the case of the "com.ibm.team.filesystem.workitems.change_set" link type id, the source reference is a change set handle (IChangeSetHandle) and the target is a work item handle (IWorkItemHandle).
To search for change sets associated with a given work item, you'd use findLinksByTarget. To search for work items associated with a given change set, you'd use findLinksBySource.
To get the resulting item handles from the ILinks in the result, use:
IReference ref = link.getSourceReference(); // or getTargetReference()
if (ref.isItemReference()) {
IItemReference itemRef = (IItemReference) ref;
IItemHandle itemHandle = itemRef.getReferencedItem();
}
Then cast the itemHandle down to IChangeSetHandle or IWorkItemHandle as appropriate.
page 1of 1 pagesof 2 pages