It's all about the answers!

Ask a question

Programmatic query to represent WI with attribute set to value among multiple values


Wendy Raschke (306) | asked Nov 10 '17, 4:07 p.m.
edited Nov 14 '17, 5:23 a.m. by Ralph Schoon (56.6k23642)

I have written code to query for work items containing certain values in specific attributes.

The work item type has custom attribute "Profile/Edition/Delivery Vehicle" and the query wants to look for WIs where this attribute's value can be any of these values:

- Liberty
- Open Liberty
- Migration Toolkit
- Eclipse Toolkit/WDT

(My screenshot can make crystal clear what I'm trying to say in words, but this forum is not allowing me to attach an image.)

My code that tries to mimic this is like so (understand that I've omitted other expressions in order to simplify this post):

       Term workItems = new Term(Operator.AND);
        IAttribute profileEditionAttr = repo.findAttribute("profileOrEdition");
        IQueryableAttribute profileEditionQueryable = repo.findQueryableAttribute("profileOrEdition");
       
        Identifier<? extends ILiteral> liberty = repo.findLiteralByName("Liberty", profileEditionAttr);
        AttributeExpression libertyExpression = new AttributeExpression(profileEditionQueryable,
                                                                                 AttributeOperation.EQUALS,
                                                                                 liberty);
        Identifier<? extends ILiteral> openLiberty = repo.findLiteralByName("Open Liberty", profileEditionAttr);
        AttributeExpression olExpression = new AttributeExpression(profileEditionQueryable,
                AttributeOperation.EQUALS,
                openLiberty);

        Identifier<? extends ILiteral> wdt = repo.findLiteralByName("Eclipse Tools/WDT", profileEditionAttr);
        AttributeExpression wdtExpression = new AttributeExpression(profileEditionQueryable,
                AttributeOperation.EQUALS,
                wdt);
       
        Identifier<? extends ILiteral> migration = repo.findLiteralByName("Migration Toolkit", profileEditionAttr);
        AttributeExpression migrationExpression = new AttributeExpression(profileEditionQueryable,
                AttributeOperation.EQUALS,
                migration);

        // TODO: Only one expression for profileEdition works
        // Adding all four results in empty query.
        workItems .add(libertyExpression);
        workItems .add(olExpression);
        workItems .add(wdtExpression);
        workItems .add(migrationExpression);

        / Sort by id /
        SortCriteria byId = new SortCriteria(repo.findQueryableAttribute(IWorkItem.ID_PROPERTY), true);
       
        / Create statement /
        Statement s = new Statement(new SelectClause(), newItemsToBridgeToGHE, new SortCriteria[] { byId });

        // Blah blah, execute query and etc

The query will return zero results if I add all those expressions to the Term object. However, if I add only one of those--like, libertyExpression, which represents the value of "Liberty" for that attribute--the query returns the expected work items.

Again, I want to query for WIs that can have any one of those values for "Profile/Edition." If I can accomplish that very simple goal with a query created in browser client, surely this must be possible through the APIs, correct?

And note that I am also having the same problem with built-in attribute "Planned For."



Accepted answer


permanent link
Ralph Schoon (56.6k23642) | answered Nov 14 '17, 9:40 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER
edited Nov 14 '17, 9:42 a.m.

This code works for me. It basically creates an expression "Priority High" one expression "Priority Medium", then it creates a Term for Priority High or Medium.
It creates an expression for "In Project Area" and "Is Type". Then it creates a final term
InProjectArea AND isType AND isPriorityHighOrMedium by adding the Term it constructed in the beginning.
I did only a quick test, but it returned the number of objects I expected as I made this up.


        IAuditableCommon auditableCommon = (IAuditableCommon) teamRepository
                .getClientLibrary(IAuditableCommon.class);    
IWorkItemCommon workitenCommon = (IWorkItemCommon) teamRepository .getClientLibrary(IWorkItemCommon.class);

    IQueryableAttribute queryablePrio = QueryableAttributes.getFactory(
            IWorkItem.ITEM_TYPE).findAttribute(projectArea,
            IWorkItem.PRIORITY_PROPERTY, auditableCommon, monitor);
    IAttribute prioAttrib = workitenCommon.findAttribute(projectArea, IWorkItem.PRIORITY_PROPERTY, monitor);

    // Prio High or Medium
    Identifier&lt;? extends ILiteral&gt; high = getLiteralEqualsString("High", workitenCommon, prioAttrib);
    Expression isHigh = new AttributeExpression(queryablePrio,
            AttributeOperation.EQUALS, high);

    Identifier<!--? extends ILiteral-->&lt;? extends ILiteral&gt; med = getLiteralEqualsString("Medium", workitenCommon, prioAttrib);
    Expression isMed = new AttributeExpression(queryablePrio,
            AttributeOperation.EQUALS, med);

    Term priorityHighOrMedium = new Term(Term.Operator.OR);
    priorityHighOrMedium.add(isHigh);
    priorityHighOrMedium.add(isMed);

    // Project Area And Type
    IQueryableAttribute queryProjectArea = QueryableAttributes.getFactory(
            IWorkItem.ITEM_TYPE).findAttribute(projectArea,
            IWorkItem.PROJECT_AREA_PROPERTY, auditableCommon, monitor);

    Expression inProjectArea = new AttributeExpression(queryProjectArea,
            AttributeOperation.EQUALS, projectArea);

    IQueryableAttribute type = QueryableAttributes.getFactory(
            IWorkItem.ITEM_TYPE).findAttribute(projectArea,
            IWorkItem.TYPE_PROPERTY, auditableCommon, monitor);

    Expression isType = new AttributeExpression(type,
            AttributeOperation.EQUALS, workitemTypeID);

    Term typeinProjectArea = new Term(Term.Operator.AND);
    typeinProjectArea.add(inProjectArea);
    typeinProjectArea.add(isType);
    // Add Medium Or High
    typeinProjectArea.add(priorityHighOrMedium);
Wendy Raschke selected this answer as the correct answer

Comments
Wendy Raschke commented Nov 14 '17, 11:15 a.m. | edited Nov 14 '17, 11:16 a.m.

So, after another revision pass of my code, using the above code snippet provided by Ralph as a model to use, the programmatic query now works properly. To re-iterate, problem was not the usage of an internal utility class to get the proper Identifier object representing the enumeration value (or whatever you call it). That remains the same. The key was in creating separate Term objects with Operator.OR that represents that WI can have one of specified values for "Profile/Edition" and any of etc values for "Planned For." Then adding those two Term objects to the Term object created with Operator. AND.

Thank you!

2 other answers



permanent link
Ulf Arne Bister (1.3k8) | answered Nov 11 '17, 12:42 p.m.

Does it succeed if you try  

Term workItems = new Term(Operator.OR); 
instead?


Comments
Wendy Raschke commented Nov 13 '17, 8:09 p.m. | edited Nov 14 '17, 4:25 a.m.

No, it doesn't work. :(

I get this error:

org.eclipse.core.runtime.AssertionFailedException: assertion failed:


Ralph Schoon commented Nov 14 '17, 4:35 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

AND operation does not seem to make sense as the attribute can always ever only be one of the four values. The AssertionFaliedException truly has more information. Maybe investigate what it is trying to tell you. Likely something wrong with the code.


permanent link
Ralph Schoon (56.6k23642) | answered Nov 14 '17, 4:26 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER
edited Nov 14 '17, 4:26 a.m.

I have explained what I have tried here: https://rsjazz.wordpress.com/2012/11/19/using-expressions-for-automation/
You are using your own utility classes, so there is no way anyone out here is going to be able to help. Have you considered to talk to others in your internal community, should you be aware of anyone?


Comments
Wendy Raschke commented Nov 14 '17, 8:29 a.m. | edited Nov 14 '17, 8:29 a.m.

I'm using a custom utility class to get the Identifier, yes, true, but that's it. I don't see how that makes much difference--since I can confirm that when I use only one and any one of expression to add to the Term object, the query works (it returns expected work items having that value for the attribute).

No one in my "internal community" knows the answer--which is why I came here. I am using RTC client APIs, which I thought was the within the purvue of this forum?


Ralph Schoon commented Nov 14 '17, 8:48 a.m. | edited Nov 14 '17, 8:48 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

Didn't say it was off topic. Did say I don't recognize your code. Custom code, so no way to test it without rewriting it.

Also an AND operation if you want to query for value A OR value B OR value C does not make sense. An assertion failed happens somewhere and usually provides a bit more information.

So pretty much no information anyone could work on. 

Your answer


Register or to post your answer.