It's all about the answers!

Ask a question

Adding a new enumeration value with server-side Java API in RTC


Luca Martinucci (1.0k280109) | asked Mar 07 '17, 5:41 a.m.

I have an attribute of type "enumeration list"; the enumeration is of type "database".
This attribute is automatically set by a follow-up action: the Java extension "calculates" the list to set in the attribute according to other attributes values, and then set the attribute with workItemWorkingCopy.setValue(attribute, list).
It works fine.
Anyway, it works only if the values in the list are already available in the enumeration (that is, in the database).
If the list contains a value that is not yet available, I should add it to the enumeration (that is, create a new entry in the database) before setting the attribute value.
Is it possible (using server-side Java API)?
My RTC version is 6.0.3.
My question looks very similar to this one: https://jazz.net/forum/questions/56133/how-to-programmatically-add-value-to-an-enumeration
Unfortunately, the thread does not have conclusive answer.

Accepted answer


permanent link
Luca Martinucci (1.0k280109) | answered Mar 14 '17, 8:51 a.m.
edited Mar 14 '17, 8:59 a.m. by Ralph Schoon (59.4k23642)

Working Code:

   @SuppressWarnings("unchecked") 
    public void addEnumerationLiteral (IAttribute attribute, String identifierName, String identifierCode) 
throws TeamRepositoryException { Enumeration enumeration= (Enumeration) enumerationService.resolveEnumeration(attribute); if (enumeration != null) { Enumeration enumCopy= (Enumeration) enumeration.getWorkingCopy(); Literal literal = EnumerationFactory.eINSTANCE.createLiteral(); com.ibm.team.workitem.common.internal.util.Utils.initNew(literal); IEnumeration<?> iEnumeration = this.workItemCommon.resolveEnumeration((IAttributeHandle) attribute.getItemHandle(), this.monitor); if (identifierCode==null) { identifierCode = getNextEnumerationIdentifierString(iEnumeration); } literal.setIdentifier(identifierCode); literal.setName(identifierName); literal.setSequenceValue(((Enumeration) enumeration).getLiterals().size()-1);

        ((Enumeration) enumCopy).getLiterals().add(literal);

        if (((Enumeration) enumCopy).getLiterals().size() == 1) { 
            ((Enumeration) enumCopy).setDefaultLiteralId(literal.getIdentifier());     
        } 
        // asynchronous operation? 
        enumerationService.update((Enumeration) enumCopy);             
    } 
}

public ILiteral getLastEnumerationLiteral (IEnumeration<?> enumeration) { 
    ILiteral lastLiteral; 
    List<?> literals = enumeration.getEnumerationLiterals(true); 
    List<ILiteral> orderedLiterals = new ArrayList<ILiteral>();  
    for (Iterator<?> literalsIterator = literals.iterator(); literalsIterator.hasNext();) { 
        // default: last position 
        int orderedPosition = orderedLiterals.size(); 
        ILiteral literal = (ILiteral) literalsIterator.next(); 
        Hashtable<String, String> currentLiteralInfo = this.getLiteralStringInfo(literal); 
        String currentLiteralNumberString = currentLiteralInfo.get("number"); 
        Integer currentLiteralNumber = null; 
        if (currentLiteralNumberString!=null) { 
            currentLiteralNumber = Integer.parseInt(currentLiteralNumberString); 
        } 
        if (currentLiteralNumber!=null) { 
            for (int i = 0; i<orderedLiterals.size(); i++) { 
                Hashtable<String, String> orderedLiteralInfo = this.getLiteralStringInfo(orderedLiterals.get(i)); 
                String orderedLiteralNumberString = orderedLiteralInfo.get("number"); 
                Integer orderedLiteralNumber = null; 
                if (orderedLiteralNumberString!=null) { 
                    orderedLiteralNumber = Integer.parseInt(orderedLiteralNumberString); 
                } 
                if (orderedLiteralNumber!=null) { 
                    if (currentLiteralNumber<orderedLiteralNumber) { 
                        orderedPosition = i; 
                        break; 
                    }      
                } 
            } 
            orderedLiterals.add(orderedPosition, literal);                  
        } 
    } 
    lastLiteral = orderedLiterals.get(orderedLiterals.size()-1); 
    return lastLiteral; 
}

public String getNextEnumerationIdentifierString (IEnumeration<?> enumeration) { 
    // avoid using when adding multiple identifiers all at once 
    String nextIdentifierString = ""; 
    ILiteral lastLiteral = this.getLastEnumerationLiteral(enumeration); 
    Hashtable<String, String> lastLiteralInfo = this.getLiteralStringInfo(lastLiteral); 
    String prefix = ""; 
    String letter = ""; 
    String numberString = null; 
    prefix = lastLiteralInfo.get("prefix"); 
    letter = lastLiteralInfo.get("letter"); 
    numberString = lastLiteralInfo.get("number");     
    if ((!prefix.isEmpty()) && (!letter.isEmpty()) && (!numberString.isEmpty())) { 
        Integer nextNumber = Integer.parseInt(numberString) + 2; 
        nextIdentifierString = prefix + "." + letter + nextNumber.toString();              
    } 
    return nextIdentifierString; 
}

public Hashtable<String, String> getLiteralStringInfo (ILiteral literal) { 
    Hashtable<String, String> literalStringInfo = new Hashtable<String, String>(); 
    String prefix = ""; 
    String letter = ""; 
    Integer number = null;

// ibm.enumeration.waivertype.literal.l2 String literalRegularExpression = "^(.+)\.(\D+)(\d+)$"; Pattern literalPattern = Pattern.compile(literalRegularExpression); Matcher literalMatcher = literalPattern.matcher(literal.getIdentifier2().getStringIdentifier()); while (literalMatcher.find()) { prefix = literalMatcher.group(1); letter = literalMatcher.group(2); number = Integer.parseInt(literalMatcher.group(3)); literalStringInfo.put("prefix", prefix); literalStringInfo.put("letter", letter); literalStringInfo.put("number", number.toString()); }
return literalStringInfo; }

Ralph Schoon selected this answer as the correct answer

One other answer



permanent link
Ralph Schoon (59.4k23642) | answered Mar 07 '17, 6:42 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

 I have never seen code for that. It is obviously somehow possible, as the Eclipse client and the Web UI provide this. All you can do is to search for IEnumeration and hope to find something that hints how this can be done.


I found com.ibm.team.workitem.service.internal.WorkItemRepositoryService.addLiteralToPersistedEnumeration(IEnumerationService, IAttribute, Identifier) doing so and that could be an entry point for you into the SDK. Good luck!


Comments
Luca Martinucci commented Mar 14 '17, 8:46 a.m.

Ralph, actually, it worked.
I managed to add this enumeration by reusing the code in the addLiteralToPersistedEnumeration, with some modifications.
Just be aware that I suspect that the update method is asynchronous, as I noticed that, when I get the added identifier, later in the extension, it is sometimes null.
I solved this problem by surrounding the get method with a while cycle (I recheck the identifier value every 1000 ms, until it is not null).
Actually, it can take up to 10 seconds for the new identifier to be committed to the database.


Ralph Schoon commented Mar 14 '17, 8:57 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

 Luca, you are most likely seeing a cash refresh delay. Another customer mentioned something here on the forum.


Ralph Schoon commented Mar 14 '17, 9:01 a.m. | edited Mar 14 '17, 9:01 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

 ps, you can use the "View HTM Source" button looks like a paper with <> on it to the top right" and add a [pre] [/pre] tag (with <, and .>) To make the code easier to read.


I did that to your code below, you can use edit and  the "View HTM Source" button to see what I did.

Your answer


Register or to post your answer.