Script Runner - Multi User Picker field validation Edited

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

2 votes

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

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!

 

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

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

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

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

Perfect :)

Thanks, Dyelamos, for your support on this!

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

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

Suggest an answer

Log in or Sign up to answer
How to earn badges on the Atlassian Community

How to earn badges on the Atlassian Community

Badges are a great way to show off community activity, whether you’re a newbie or a Champion.

Learn more
Community showcase
Published Sunday in Agility

You asked for it, so we delivered: images on issues have arrived

A picture tells a thousand words. And agility boards have just released their latest feature: cover images on issues – so now your board can tell a story at first glance. Upload attachmen...

207 views 2 11
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you