Script Runner - Multi User Picker field validation

Tom104Tom December 1, 2017

Hi,

I'm trying to create a simple scripted validator via Script Runner that compares two multi user picker fields (Type: Collection):

Actual Fruits contains: apple, banana
Necessary Fruit List contains: apple, banana, orange

If the Actual Fruits field contains at least one value from the Necessary Fruit List, the validation should be true. The Actual Fruits field can contain also two, more or other fruits, but it needs to validate true if at least one fruit is there from the Necessary Fruit List.

I tried the following codes, but all of them are validating false:

cfValues['Actual Fruits']*.name.contains(cfValues['Necessary Fruit List']*.name

cfValues['Actual Fruits']*.name.contains(cfValues['Necessary Fruit List']*.name.any())

cfValues['Actual Fruits']*.name.contains(cfValues['Necessary Fruit List']*.name).any()

Thanks for your help.

Example assertion below:

2017-12-01 15_22_59-B7400316 - Remote Desktop Connection - __Remote.png

 2017-12-01 15_26_46-B7400316 - Remote Desktop Connection - __Remote.png

2 answers

1 accepted

Suggest an answer

Log in or Sign up to answer
2 votes
Answer accepted
Daniel Yelamos [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 6, 2017

Ah!

Apologies, I thought your actual fruits only had 1 value. If it's a list you are going to have to use Collection.intersect()

So for example, you could do this:

def actualFruitNames = cfValues['Actual Fruits']*.name
assert actualFruitNames.size() == cfValues['Necessary Fruit List']*.name.intersect(actualFruitNames).size()

 That is basicall asserting that the intersection of the two sets is the same as the original set. Which will only be true if your main set is a subset of the original one.

Does that make sense?

Hope this helped, if you need any more help, please do say, and if this helped, please accept and upvote my answer so that other users can benefit from this question.

Cheers!

Dyelamos

Tom104Tom December 7, 2017

I think the assert function is not working very well on this code, so I've just tested the code without asserting and just checked the outcome (true, false) by testing it as a condition. This seems to work, but it also brought me here (thanks for the hint!):

http://mrhaki.blogspot.co.at/2010/03/groovy-goodness-intersect-collections.html

I'm currently testing this one with disjoint:


We can use the disjoint() to test if both collections contain common elements are not.


!cfValues['Actual Fruits']*.name.disjoint(cfValues['Necessary Fruit List']*.name)

So far, the above code also works (and validates true) i.e. if lemon approves together with some necessary fruit, although lemon itself is not part of the Necessary Fruit List. For certain reasons, this could be the case in my actual scenario (just came to my mind, didn't specify that in my initial request).

Two questions:

1. Is disjoint a reliable solution in your opinion for my scenario or was it just luck that my test cases were successful?

2. The only problem with this code is that if the Actual Fruits list is empty, the code returns an error, not a false. Can I somehow prevent this from resulting in an error but instead just resulting in a false?

Error message if

Actual Fruits: no objects (empty)
Necessary Fruit List: apple, banana, orange

Cannot invoke method disjoint() on null object

Cheers!

 

Tom104Tom December 7, 2017

Ah, sorry, easy:

if (cfValues['Actual Fruits']) {
!cfValues['Actual Fruits']*.name.disjoint(cfValues['Necessary Fruit List']*.name)
} else {
false;
}

I think that's it, or? I can cover the following use-cases now:

Necessary Fruit List: apple, banana, orange

Actual Fruits: no objects (empty) > false
Actual Fruits: lemon > false
Actual Fruits: banana > true
Actual Fruits: banana, lemon > true
Actual Fruits: apple, banana, orange, lemon > true

Daniel Yelamos [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 11, 2017

Hey Tom.

I don't understand why you are using disjoint instead of intersect. Disjoint might not fully work as you intend, since it isn't taking into consideration what intersects with each set, but what doesn't intersect. 

If this does work for you, go ahead, but if you found that assert was the problem, why don't you use my original code with the intersect?

Cheers!

Dyelamos

Daniel Yelamos [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 11, 2017
Tom104Tom December 11, 2017

Hi Dyelamos,

sorry, I somehow missed to explain why intersec did not work for me. Using intersec, the validation will be false if there's another fruit in Actual Fruits that is not in the Necessary fruit list:

Necessary Fruit List: apple, banana, orange
Actual Fruits: banana, lemon > false

although banana is there and it should validate true.

As mentioned above, I didn't think of this scenario when creating the initial question, but it is possible in my actual use-case.

Using NOT disjoint however works (!...disjoint...). It will validate

Actual Fruits: banana, lemon > true

Daniel Yelamos [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 11, 2017

Hello Tom.

Sorry I misunderstood you. Yes you are correct, for that use case, disjoint might work. However I'm not 100% sure if there are any edge cases that might fail with this.

Give it a go, and see if it works. If you have any problems with it, I'll be glad to have another look.

Could you accept one of the answers so that people know this has been answered?

Cheers!

Dyelamos

Tom104Tom December 11, 2017

Perfect :)

Thanks, Dyelamos, for your support on this!

J Manas Kumar February 6, 2020

Hi @Tom104Tom 

 

I have a requirement to update one multi user picker field if its child issue gets updated .

But i am not even able to do this using Listener.

i went through your questions.

Can you provide little bit help for the groovy script, as i am new this thing.

Will be highly appreciated if you can..

 

Regards

Manas

0 votes
Daniel Yelamos [Adaptavist]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 5, 2017

Hi Tom!

So this is happening because you are using some concepts that aren't in groovy.

Your line:

cfValues['Actual Fruits']*.name.contains(cfValues['Necessary Fruit List']*.name

Is using contains, which implies that the left part of the operator should contain at least the totality right part of the operator.

However, you want that the left part of the operator, contains at least, an element of the subset that is your right part operator.

In order to do that, you need to use the operator in like so:

cfValues['Actual Fruits']*.name in cfValues['Necessary Fruit List']*.name

Hope this helped, if you need anymore help, please do say, and if this helped, please accept and upvote my answer so that other users can benefit from this question.

Cheers!

Dyelamos

Tom104Tom December 6, 2017

Hi Dyelamos,

thanks for your help. Understood, but unfortunately this also still validates false.

2017-12-06 13_56_06-B7400316 - Remote Desktop Connection - __Remote.png

TAGS
AUG Leaders

Atlassian Community Events