Manipulating Work Item Enumeration Values


I ran into the mysteries of Enumerations in the Java API several times and there is a question on the Jazz Forum right now how to get and set enumeration type values using the Java API. Lets look at it, it is really easy.

The post A RTC WorkItem Command Line Version 2 uses this technique to find, set and remove literals fro enumeration and enumeration list attribute types.

License and how to get started with the RTC API’S

As always, our lawyers reminded me to state that the code in this post is derived from examples from Jazz.net as well as the RTC SDK. The usage of code from that example source code is governed by this license. Therefore this code is governed by this license, which basically means you can use it for internal usage, but not sell. Please also remember, as stated in the disclaimer, that this code comes with the usual lack of promise or guarantee. Enjoy!

If you just get started with extending Rational Team Concert, or create API based automation, start with the post Learning To Fly: Getting Started with the RTC Java API’s and follow the linked resources.

You should be able to use the following code in this environment and get your own automation or extension working.

To keep it simple this example is, as many others in this blog, based on the Jazz Team Wiki entry on Programmatic Work Item Creation and the Plain Java Client Library Snippets. The example in this blog shows RTC Client and Common API.

Download the Code

The example code can be downloaded from DropBox. Please note, there might be restrictions to access DropBox and the code in your company or download location.

The Code Explained

The code below is client code. Code in the server would be very similar, except that the Client Library would be replaced by a service.

When accessing the value of a work item attribute using Object value = workItem.getValue(iAttribute); objects of various types are returned. For Enumeration attribute types the returned value is an Identifier. You can use the code below to get the data.

if (value instanceof Identifier) {
	Identifier literalID = (Identifier) value;
	ILiteral literal = getLiteralbyID(literalID, iAttribute);
	String displayValue = literal.getName();
}

The code to get the literal by its ID looks as follows:

private ILiteral getLiteralbyID(Identifier findLliteralID, IAttributeHandle iAttribute) throws TeamRepositoryException {
	IWorkItemClient workItemClient = (IWorkItemClient) teamRepository().getClientLibrary(IWorkItemClient.class);
	IEnumeration enumeration = workItemClient.resolveEnumeration(iAttribute, null);

	List literals = enumeration.getEnumerationLiterals();
	for (Iterator iterator = literals.iterator(); iterator.hasNext();) {
		ILiteral iLiteral = (ILiteral) iterator.next();
		if (iLiteral.getIdentifier2().equals(findLliteralID)) {
			return iLiteral;
		}
	}
	return null;
}

If you have a string value and need to set the work item attribute value of an enumeration type attribute you can use the code below. It looks up the literals and compares their display value to the string it is looking for. Then it sets the value.

Note: You need to get a WorkItemWorkingCopy before you can set the value of a work item attribute, otherwise you will receive an exception saying that the item is immutable. The best way to get a WorkItemWorkingCopy is to use a WorkItemOperation as explained in this post.

workItem.setValue(priority, getLiteralEqualsString(fPriorityEnumerationString,workItemClient, priority));

Finding the literal happens in the code below:

private static Identifier getLiteralEqualsString(String name, IAttributeHandle ia) throws TeamRepositoryException {
	IWorkItemClient workItemClient = (IWorkItemClient) teamrepository.getClientLibrary(IWorkItemClient.class);

	Identifier literalID = null;
	IEnumeration enumeration = workItemClient.resolveEnumeration(ia, null); // or IWorkitemCommon
	List literals = enumeration.getEnumerationLiterals();
	for (Iterator iterator = literals.iterator(); iterator.hasNext();) {
		ILiteral iLiteral = (ILiteral) iterator.next();
		if (iLiteral.getName().equals(name)) {
			literalID = iLiteral.getIdentifier2();
			break;
		}
	}
	return literalID;
}

Common API

Please note, the example above uses the IWorkItemClient interface, however, the enumeration relevant interface is just inherited from the interface com.ibm.team.workitem.common.IWorkItemCommon . This interface can be used in the client as well as the server API.

Summary

This post explains the basics of the RTC Enumeration API and how to access and use enumeration literals in automation.

I hope this code will help others struggling with the RTC Java API.

Advertisements

About rsjazz

Hi, my name is Ralph. I work for IBM and help colleagues and customers with adopting the Jazz technologies.
This entry was posted in Jazz, RTC, RTC Extensibility and tagged , , , , . Bookmark the permalink.

19 Responses to Manipulating Work Item Enumeration Values

  1. Clement Liu says:

    Hi Ralph, thanks for the code and it works pretty well. And is there any way to add values to an exiting enumeration which in our case is stored in the project process specification? I’ve found Nick’s comments in this post – https://jazz.net/forum/questions/56133/how-to-programmatically-add-value-to-an-enumeration
    Would you also recommend the the process area working copies API? Thank you!

    • rsjazz says:

      Clement, I haven’t looked into that API. I would assume that you can add enumeration values to enums stored in the process XML, but it could require unsupported modification of the Process XML or internal API.

  2. Daniel Chirillo says:

    Which ILiteral is used in these snippets?
    com.ibm.team.repository.common.query.ast.ILiteral
    com.ibm.team.workitem.api.common.ILiteral
    com.ibm.team.workitem.common.model.ILiteral

  3. YingYing Cheng says:

    Have used the following code to retrieve all enumeration values, Thanks a lot. Ralph. It’s a really helpful and practical article.

    IAttribute phaseAttribute = workItemClient.findAttribute(projectArea, “howfound”, null);
    Identifier literalID_phase = null;
    IEnumeration enumeration_phase =workItemClient.resolveEnumeration(phaseAttribute, null);
    List literals_phase = enumeration_phase.getEnumerationLiterals();
    for (Iterator iterator = literals.iterator(); iterator.hasNext();) {
    ILiteral iLiteral = (ILiteral) iterator.next();
    System.out.println(“Phase Name:”+iLiteral.getName());
    System.out.println(“Phase Identifier2:” + iLiteral.getIdentifier2());
    if (iLiteral.getName().equals(phaseFound)) {
    literalID_phase = iLiteral.getIdentifier2();
    System.out.println(“You found phase!!”);
    // break;
    }
    }
    if(literalID_phase==null){
    System.out.println(“not found phase”);
    return false;
    }

  4. Bruno Fazolli says:

    Hi Ralph
    I was implementing the code to set workitem attribute value of an enumeration type attribute by but I got an error while running “setvalue” (last line). Do you have any tip?

    Thanks in advance.
    Bruno Fazoli

    • rsjazz says:

      Please don’t spam the comments with error messages.

      Your error message translates to “you can’t modify the work item, because you don’t have a working copy”

      Search the blog for examples how it is done e.g. using a WorkItemOperation.

  5. Bruno Fazolli says:

    Hi All, I was able to fix that. Need to use WorkItemWorkingCopy. Check the code:

    int id = Integer.parseInt(defect.getBugId());
    IProjectArea projectArea;

    IWorkItem workItem = workItemClient.findWorkItemById(id, IWorkItem.FULL_PROFILE, null);
    projectArea = findProjectArea(teamRepository, PROJECT_AREA_NAME);

    IAttribute workitemEqualizationStatusAtribute = workItemClient.findAttribute(projectArea, CustomWorkItemAttrubutes.WORKITEM_EQUALIZATION , null);

    IWorkItemWorkingCopyManager mgr = workItemClient.getWorkItemWorkingCopyManager();
    mgr.connect(workItem, IWorkItem.FULL_PROFILE, null);

    WorkItemWorkingCopy copy = mgr.getWorkingCopy(workItem);
    IWorkItem workItemCopy = copy.getWorkItem();

    Identifier literalID = null;
    IEnumeration enumeration = workItemClient.resolveEnumeration(workitemEqualizationStatusAtribute, null); // or IWorkitemCommon
    List literals = enumeration.getEnumerationLiterals();
    for (Iterator iterator = literals.iterator(); iterator.hasNext();) {
    ILiteral iLiteral = (ILiteral) iterator.next();
    if (iLiteral.getName().equals(defect.getWorkitemEqualizationStatus())) {
    literalID = iLiteral.getIdentifier2();
    break;
    }
    }

    workItemCopy.setValue(workitemEqualizationStatusAtribute, literalID);
    copy.save(null);

  6. Jafar Ali says:

    I am writing a generic code to set a Attribute value. Is there a way to distinguish between IAttribute of Enumeration type?

  7. jafar ali says:

    Can you please tell me how can i differentiate between Enumeration and Enumeration List attribute type.

    • rsjazz says:

      You can use com.ibm.team.workitem.common.model.AttributeTypes.isEnumerationListAttributeType(String) with the com.ibm.team.workitem.common.model.IAttribute.getAttributeType().

      The attribute itself needs to be set using a List and it also returns an Objcc that is a List. There is code in the work Item Commandline you could look up. I agree it is not trivial.

  8. jafar ali says:

    Thanks for a quick reply.

  9. Mathieu says:

    Hello Ralph,
    I would like to get the name of an enumeration, not the name of each literal values. Just the name on the corresponding name to the enumeration ID.
    I have tried to search a method .getName() on IEnumeration … It doesnt exist …
    Can you help me ?
    Regards
    Mathieu

    • rsjazz says:

      I never had the need, so I don’t have the code. If you look closer, you find an com.ibm.team.workitem.client.IEnumerationClient and can use its resolveEnumerations to retrieve the Enumerations as array of class Enumeration.Enumeration seems to have the name of the Enumeration.

      I have never had the need to find that and I am not sure how to get there from the litral.

      • Mathieu says:

        Thanks Ralph for your advise.
        I have tried this code :

        IEnumerationClient enumerationClient = (IEnumerationClient) this.teamRepository.getClientLibrary(IEnumerationClient.class) ;
        Enumeration[] enumerationTab = enumerationClient.resolveEnumerations(iProjectArea.getProjectArea(), monitor ) ;
        for (Enumeration enumeration : enumerationTab) {
        if (enumeration.getIdentifier().equals(enumerationId)) {
        enumerationName = enumeration.getName() ;
        }
        }

        Unfortunately, the object enumerationTab is empty ….
        I continue to investigate on this problem

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s