Jazz Forum Welcome to the Jazz Community Forum Connect and collaborate with IBM Engineering experts and users

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

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.

0 votes


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

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

1 vote


3 other answers

Permanent link

 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!

1 vote

Comments

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.

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

 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

 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

0 votes


Permanent link
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

0 votes

Comments

 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>

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

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.  

Search context
Follow this question

By Email: 

Once you sign in you will be able to subscribe for any updates here.

By RSS:

Answers
Answers and Comments
Question details
× 10,927

Question asked: Mar 07 '17, 5:41 a.m.

Question was seen: 4,154 times

Last updated: Jan 22, 10:02 a.m.

Confirmation Cancel Confirm