It's all about the answers!

Ask a question

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


Luca Martinucci (1.0k294112) | asked Mar 07 '17, 5:41 a.m.
closed Jan 22, 10:00 a.m. by Ralph Schoon (63.1k33646)

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.

The question has been closed for the following reason: "The question is answered, right answer was accepted" by rschoon Jan 22, 10:00 a.m.

Accepted answer


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

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

3 other answers



permanent link
Ralph Schoon (63.1k33646) | 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.


permanent link
Mohammed Alawneh (261) | answered Jun 01 '23, 8:58 a.m.
edited Jun 01 '23, 9:03 a.m.

 Hi All


The accepted answer is really useful! Thanks.

I am sharing the following code that i used to add new literals through Java Plain APIs (Client Side SDK)  and it's working fine.


    @SuppressWarnings("unchecked")
    public static void addEnumerationLiteral(IAttribute attribute, String identifierName, String iconUrl)
            throws TeamRepositoryException {
        IEnumerationService enumerationService = (IEnumerationService) ((TeamRepository) CLMConnection.teamRepository)
                    .getServiceInterface(IEnumerationService.class);
        Enumeration enumeration = (Enumeration) enumerationService.resolveEnumeration(attribute);
        if (enumeration != null) {
            Enumeration enumerationCopy = (Enumeration) enumeration.getWorkingCopy();
            List<literal> literalsCopy = enumerationCopy.getLiterals();
            Literal newLiteral = EnumerationFactory.eINSTANCE.createLiteral();
            newLiteral.setIdentifier(getNewLiteralIdentifier(enumeration));
            newLiteral.setName(identifierName);
            newLiteral.setSequenceValue(((Enumeration) enumeration).getLiterals().size() - 1);
            newLiteral.setIconUrl(iconUrl);
            literalsCopy.add(newLiteral);
            if (literalsCopy.size() == 1) {
                enumerationCopy.setDefaultLiteralId(newLiteral.getIdentifier());
            }
            enumerationService.update(enumerationCopy);
        }
    }
</literal>
    public static String getNewLiteralIdentifier(Enumeration enumeration) {
        Literal lastLiteral = (Literal) enumeration.getLiterals().get(enumeration.getLiterals().size() - 1);
        String lastLiteralIdentifier = lastLiteral.getIdentifier();
        return getNextId(lastLiteralIdentifier);
    }
    public static String getNextId(String id) {
        String[] parts = id.split("(?=\d+$)", 2);
        return parts[0] + String.format("%0" + parts[1].length() + "d", Integer.parseInt(parts[1]) + 1);
    }


Hope this helps someone!

Thanks,
Mohammad Alawneh


permanent link
Manju Gowda (37110) | answered Jan 18, 3:14 a.m.
edited Jan 18, 3:19 a.m.
I tried the way you have implemented. Looks no error but i am getting null value at

Enumeration enumeration = (Enumeration) enumerationService.resolveEnumeration(attribute);

Also tried

enumerationService.resolveEnumerations(getProjectArea());

which is giving empty array.
Can you please help me what am i missing here.
I am using EWM 7.0.2 SR1 version.

Thanks in advance,
Manju

Comments
Mohammed Alawneh commented Jan 18, 5:55 a.m. | edited Jan 18, 5:55 a.m.

 Hi Manju,


Make sure the attribute type you are using is Database Enumeration. You should see these options whenever you're creating a new enumeration:

Add Enumeration
<button aria-label="close" class="jazz-ui-Dialog-close-button" dojoattachpoint="closeButton" style="border-color: transparent; border-style: solid; cursor: pointer; font-family: inherit; font-size: 12px; height: 48px; overflow: hidden; padding: 12px; position: absolute; right: 0px; top: 0px; transition: background-color 0.11s cubic-bezier(0.2, 0, 0.38, 0.9) 0s; width: 48px;">
</button>
<label for="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumNameField" style="color: rgb(102, 102, 102);"> Name: </label> <input dojoattachpoint="enumNameField" id="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumNameField" style="font-family: Arial, sans-serif; font-size: 9pt; margin: 0px; padding-bottom: 0px; padding-top: 0px; width: 441.378px;">
<label for="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumIdField" style="color: rgb(102, 102, 102);"> ID: </label>  * <input dojoattachevent="onchange:_handleIdChanged" dojoattachpoint="enumIdField" id="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumIdField" style="font-family: Arial, sans-serif; font-size: 9pt; margin: 0px; padding-bottom: 0px; padding-top: 0px; width: 441.378px;">
<label for="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_externalValueField" style="color: rgb(102, 102, 102);"> External URI: </label> <input dojoattachevent="onchange:_handleExternalValueChanged" dojoattachpoint="externalValueField" id="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_externalValueField" style="font-family: Arial, sans-serif; font-size: 9pt; margin: 0px; padding-bottom: 0px; padding-top: 0px; width: 441.378px;">

<label style="color: rgb(102, 102, 102);"> Choose where to store the Enumeration: </label>
<input checked="checked" id="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumStoreInProcessField" name="enumStore" style="font-family: Arial, sans-serif; font-size: 9pt; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding: 0px;" type="radio">   <label for="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumStoreInProcessField" style="color: rgb(102, 102, 102); width: 100%;"> Process Specification (limits change permissions to project area maintainers) </label>
<input dojoattachpoint="enumStoreInDbField" id="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumStoreInDbField" name="enumStore" style="font-family: Arial, sans-serif; font-size: 9pt; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding: 0px;" type="radio">   <label for="com_ibm_team_workitem_web_process_ui_internal_view_enumeration_AddEnumerationContent_3_enumStoreInDbField" style="color: rgb(102, 102, 102); width: 100%;"> Database (allows to configure separate permissions to add new literals) </label>


Manju Gowda commented Jan 22, 6:56 a.m.

Hi @Mohammed,


Thanks for your reply.
So this code only works for the DB level Enums. Currently we are using Process Config type.
Thanks again
Manju


Ralph Schoon commented Jan 22, 10:02 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

Please do not answer with questions on an existing question. Create your own question. This is especially true, if the question is very old or already correctly answered.

Thanks.