It's all about the answers!

Ask a question

How to get attachment history (not workitem history) by plain java api?


Song Jie (364) | asked Apr 12 '17, 8:39 a.m.
edited Apr 12 '17, 9:37 a.m. by Ralph Schoon (63.1k33646)

 I've managed to get the workitem history by the following code. But it doesn't work to get attachment add/removal history. RTC web ui & eclipse client have managed to do so. They keep a history of adding/removal attachments, and adding links. How to do this in plain java?


In a similar question about getting workitem history, I got the following answer: "From reading the interface documentation the interface com.ibm.team.repository.common.IAuditable provides the com.ibm.team.repository.common.IAuditable.getPredecessorState() and com.ibm.team.repository.common.IAuditable.getMergePredecessorState() which you should be able to use to get to the history items." It works for getting workitem history, but not attachment historyBecause IReference doesn't extend IAuditable, and adding attachement is creating a kind of IReference. I noticed that the answer have been selected as the accepted answer in that question, but it's not the way to get the attachment history. 

Here's my code, you may see my struggle to get it done. I've verfied that workingCopy#getReferences().getDeletedAttachments doesn't work. Iterating every stateWi to getReferences doesn't work either. Outcome is always the current one. So after all how did RTC web ui manage to do so? Thanks a lot in advance.

public List<abstractoutputdto> fetchWorkItemCompleteStates(ITeamRepository repo, int wiid, final String outputType) throws TeamRepositoryException, RTCAdapterException {
    final ResettingTimer t = new ResettingTimer(this, true);
    final IWorkItem currentWi = this.getWIByID(repo, wiid);
    DevLog.super_trace("current wi stateId: " + currentWi.getStateId().getUuidValue());
    final IItemManager itemManager = repo.itemManager();
    // ATTACHMENT
    IWorkItemWorkingCopyManager wcm = this.getWCM(repo);
    wcm.connect(currentWi, IWorkItem.FULL_PROFILE, null);
    WorkItemWorkingCopy wc = wcm.getWorkingCopy(currentWi);
    List<ireference> rL = wc.getReferences().getReferences(WorkItemEndPoints.ATTACHMENT);
    DevLog.debug("---------->"+rL.size());
    List<iattachmenthandle> aL = wc.getReferences().getDeletedAttachments();
    DevLog.debug("deleted attachment size:L "+aL.size());
    for (IAttachmentHandle atmtH : aL) {
        final IAttachment atmt = (IAttachment) repo.itemManager().fetchCompleteItem(atmtH, IItemManager.DEFAULT, null);
        final AtmtInfoOutputBO aiob = new AtmtInfoOutputBO();
        aiob.setAtmtName(atmt.getName());
        aiob.setDescription(atmt.getDescription());
        aiob.setCreationDate(atmt.getCreationDate() == null ? null : atmt.getCreationDate().toString());
        aiob.setId(atmt.getId());
        DevLog.debug("----eleted attachment: "+Invoker.reportObj(aiob));
    }
    // state handle list
    final List<iauditablehandle> shL = itemManager.fetchAllStateHandles((IAuditableHandle) currentWi.getItemHandle(), null);
    List<iworkitem> wiL = new ArrayList<iworkitem>();
    t.lapAndReset();
    wiL = itemManager.fetchCompleteStates(shL, null);
    t.lapAndReset();
    Class<? extends AbstractOutputDTO> oc = this.getClassByOutputType(outputType);
    DevLog.super_trace("output dto class decided to be: " + oc.getCanonicalName());
    final List<abstractoutputdto> odL = new ArrayList<abstractoutputdto>();
    for (IWorkItem stateWi : wiL) {
        DevLog.debug("Converting stateWi id: " + stateWi.getId());
        try {
            // final AbstractOutputDTO od = EnrichOByWIS.ins.enrichOByWI(repo, stateWi, oc);
            UDStateOutputDTO od = new UDStateOutputDTO();
            od.setModifiedDate(stateWi.modified().toString());
            od.setStateId(stateWi.getStateId().getUuidValue());
            // CONTRIBUTOR
            final Contributor c = (Contributor) repo.itemManager().fetchCompleteItem(stateWi.getModifiedBy(), IItemManager.DEFAULT, null);
            od.setModifiedBy_name(c.getName());
            od.setModifiedBy_emailAddress(c.getEmailAddress());
            DevLog.super_trace("returned state: " + Invoker.reportObj(od));
            odL.add(od);
        } catch (TeamRepositoryException e) {
            e.printStackTrace();
        }
        /
        * catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); }
        /
    }
    t.lapAndReset();
    return odL;
}


Comments
Ralph Schoon commented Apr 12 '17, 9:38 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

 I have no answer. I had hoped you could get the attachments from the history state.


Song Jie commented Apr 12 '17, 8:58 p.m.

 that's ok. today i'll try digging into IAuditable implements for an answer. If I find sth I'll come back to post here.

Accepted answer


permanent link
Song Jie (364) | answered Apr 12 '17, 10:56 p.m.

 GOOD NEWS!!!! IT IS DONE!!!!


The misunderstanding of "web ui capable of displaying attachment history" is from the fact that web ui mingles attachment history with workitem history. The fact is: RTC v 6.0.3 simply adds a comment to every workitem once adding/removing attachment occurs:

<style type="text/css"> p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco} span.s1 {color: #7e504f} span.s2 {color: #931a68} span.s3 {color: #3933ff} span.Apple-tab-span {white-space:pre} </style>

IComments cs = currentWi.getComments();

IComment[] cA = cs.getContents();

for(IComment c: cA){

DevLog.debug("------------"+c.getHTMLContent());

}


This will give you everything you need, exactly the same as what web ui & eclipse displays:

<style type="text/css"> p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco} </style>

2017-04-13 10:44:11.254 ContainerBackgroundProcessor[StandardEngine[Catalina]] I .....> ENTER#unit test begins.

2017-04-13 10:44:11.256 ContainerBackgroundProcessor[StandardEngine[Catalina]] T [TIMER-FetchWorkItemCompleteStatesS] Starting

2017-04-13 10:44:11.277 ContainerBackgroundProcessor[StandardEngine[Catalina]] S current wi stateId: _ivkJUR95Eee6ULi1ar8cBA

2017-04-13 10:44:11.279 ContainerBackgroundProcessor[StandardEngine[Catalina]] D ------------<synthetic>Added: attachment 38 (2598A47BA55D2B66EE32B373B232B260C02AD8AD.torrent)</synthetic>

2017-04-13 10:44:11.279 ContainerBackgroundProcessor[StandardEngine[Catalina]] D ------------<synthetic>Removed: attachment 38 (2598A47BA55D2B66EE32B373B232B260C02AD8AD.torrent)</synthetic>

2017-04-13 10:44:11.279 ContainerBackgroundProcessor[StandardEngine[Catalina]] D ------------<synthetic>Added: attachment 39 (aaa.torrent)</synthetic>

2017-04-13 10:44:11.327 ContainerBackgroundProcessor[StandardEngine[Catalina]] D attachment state list: 1



Now I'll explain a little more about my investigation on 

Q1: "why it's impossible to display attachment history at the current level"


Everything capable of displaying a history must inherits from IAuditable, but IReference is never one of the inherited. IAttachment does extend IAuditable, BUT it means historical state of the same attachment is auditable, not a list of different attachments.


Q2: How did RTC web ui display link creation data?

This is the second trick. They don't really get a history of references. As what I explained above, IReference doesn't extend IAuditable, which means it's impossible to get it's historical states. I bet they simply got a list of current references, which gives creationDate. It perfects explains why removal timestamp is not available in the history.

Ralph Schoon selected this answer as the correct answer

Comments
Ralph Schoon commented Apr 13 '17, 2:12 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

Thanks for sharing 

Your answer


Register or to post your answer.


Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.