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 for 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;
}

List Attributes such as Enumeration Lists

It is possible to define attributes for several types as list attributes that allow to select multiple values.

To set a value for such attribute types add the values the attribute is supposed to have set to a List and return that list.

You can create a typed list or an untyped list and simply add the literals as objects. See Working with Work Item Attributes in the section List Attributes and the section Set the WorkItem Attribute for an example.

A very simple example would be for a custom enumeration. Construct a list of attribute values (e.g. the Identifier for the enumeration literal) and use the list to set the values:

List values = new ArrayList();
values.add(getLiteralEqualsString("foo", customEnumerationList));
values.add(getLiteralEqualsString("bar", customEnumerationList));
workItem.setValue(customEnumerationList,values);

For more examples see the work item commandline especially the WorkItemUpdateHelper for methods ending with List for example:

com.ibm.js.team.workitem.commandline.helper.WorkItemUpdateHelper.calculateEnumerationLiteralList(ParameterValue, List)

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.

35 thoughts on “Manipulating Work Item Enumeration Values

    • 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.

  1. 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

  2. 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;
    }

  3. 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

    • 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.

  4. 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);

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

    • 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.

  6. 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

    • 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.

      • 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

  7. Hi Ralph, I have used your method getLiteralEqualsString (like many others) with great success.
    Unfortunately, I cannot use getName() since it returns a display name. In my current environment that is is changed to “%somestring” to cater for different locales.
    I would like to use the literal id (internal id) “enum.literal.something” since this “cannot” be changed. How do I get at this value using your code example? I can’t use iLiteral.getValue() since it is not defined.

    Thanks

    • Lewis,

      in the Workitem Command Line (which is always a good reference for work item API) I use

      /**
       * Find an enumeration literal if you have the ID
       * 
       * @param enumeration
       * @param identifierName
       * @return
       */
      @SuppressWarnings("unused")
      private ILiteral getEnumerationLiteralByID(
      		final IEnumeration enumeration,
      		final String identifierName) {
      	final Identifier identifier = Identifier.create(
      			ILiteral.class, identifierName);
      	return enumeration.findEnumerationLiteral(identifier);
      }
      

      The ILiteral has the methods

      com.ibm.team.workitem.common.model.ILiteral.getIdentifier2()
      com.ibm.team.workitem.common.model.ILiteral.getName()
      
    • Sorry, not my area of expertise. In general there are answers in the Jazz.net forum aroud this, there is open-services.net and if you read a work item with OSLC, you should be able to see a link to the resource definition, where I believe you ould be able to find other literals.

  8. How do we actually go through all the possible enumerations of a identifier and set it to that. Essentially two steps: 1. Get the attribute say priority 2. Go through all the enumerations of priority (low,medium, high) and then set it to one of those. So a stub would look like setUserPriority(attribute, “High”) where attribute is a priority attribute. Similarly setting owners. Get the owned by attribute, go through the list of all possible users in the project are and set to the one that the user wants. Example: setUserOwnedBy(attribute, “John Doe”).

    • Not sure if this is a question and if so, what the question would be. Obviously a user is not an enumeration. Regardless of that, if you only have a display value (or user name) you will have to search for the literal (contributor) using this value and identify the internal representation to set it. There are different ways to search, the above is only one of them.

  9. I want to set value for a enumlist attribute, but i dont know to setvalue for enumlist.
    workItemCopy.setValue(entry.getValue(),iLiteral.getIdentifier2()); set the enum value

    Similar thing for enumlist type attributes.

  10. Want a code for setting enumlist value for a workitem, actually i have code to update workitem from excel to RTC, so i want to update some enumlist attributes, so any thing similar to it will be helpful.

      • Thanks for the info but i haven’t got that, it would be good if you post the code here itself.
        Just a piece of code to setvalue for enumlist.

        That is which all parameter to pass to setvalue for enumlist attributes.

      • A code snippet of setvalue for enumlist attributes

        How to call setvalue for enumllist attributes.

      • I tried to use the same names and shortly explain what the function does. I fixed the naming/parameter order, otherwise it should be pretty clear already what it does – getting an ILiteral.

  11. Thanks for your Method ,it is very useful, I modify it to fit Server API .

    IWorkItemCommon workItemCommonsServer = this.getService(IWorkItemCommon.class);
    Object departmentValue = newWorkItem.getValue(departmentAttri);
    if (departmentValue instanceof Identifier) {
    Identifier literalID = (Identifier) departmentValue1;
    ILiteral literal = getLiteralbyID(workItemCommonsServer,literalID, departmentAttri);
    departmentNo = literal.getName();
    }

    @SuppressWarnings({ “rawtypes” })
    public ILiteral getLiteralbyID(IWorkItemCommon workItemCommonsServer,Identifier findLliteralID, IAttributeHandle iAttribute) throws TeamRepositoryException {
    IEnumeration enumeration = workItemCommonsServer.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;
    }

Leave a reply to rsjazz Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.