Skip to content

Commit bc8bc7a

Browse files
committed
GROOVY-11911: Deprecate callsite versions of BooleanClosureWrapper
1 parent 7a15884 commit bc8bc7a

13 files changed

Lines changed: 166 additions & 49 deletions

src/main/java/groovy/lang/Closure.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import org.codehaus.groovy.runtime.GeneratedClosure;
2929
import org.codehaus.groovy.runtime.InvokerHelper;
3030
import org.codehaus.groovy.runtime.InvokerInvocationException;
31-
import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
31+
import org.codehaus.groovy.runtime.BooleanClosureWrapper;
3232
import org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache;
3333
import org.codehaus.groovy.runtime.memoize.ConcurrentSoftCache;
3434
import org.codehaus.groovy.runtime.memoize.LRUCache;

src/main/java/org/codehaus/groovy/runtime/ArrayGroovyMethods.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@
3838
import groovy.util.function.IntComparator;
3939
import groovy.util.function.LongComparator;
4040
import org.apache.groovy.lang.annotation.Incubating;
41-
import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
42-
import org.codehaus.groovy.runtime.callsite.BooleanReturningMethodInvoker;
43-
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberDiv;
41+
import org.codehaus.groovy.runtime.BooleanClosureWrapper;
4442
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
43+
import org.codehaus.groovy.runtime.InvokerHelper;
44+
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberDiv;
4545
import org.codehaus.groovy.util.ArrayIterable;
4646
import org.codehaus.groovy.util.ArrayIterator;
4747
import org.codehaus.groovy.util.BooleanArrayIterator;
@@ -4319,9 +4319,8 @@ public static <T> List<T> grep(T[] self) {
43194319
*/
43204320
public static <T> List<T> grep(T[] self, Object filter) {
43214321
List<T> answer = new ArrayList<>();
4322-
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker("isCase");
43234322
for (T element : self) {
4324-
if (bmi.invoke(filter, element)) {
4323+
if (DefaultTypeTransformation.castToBoolean(InvokerHelper.invokeMethod(filter, "isCase", element))) {
43254324
answer.add(element);
43264325
}
43274326
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.codehaus.groovy.runtime;
20+
21+
import groovy.lang.Closure;
22+
23+
import java.util.Map;
24+
import java.util.function.Predicate;
25+
26+
/**
27+
* Adapts a {@link Closure} to a {@link Predicate} over {@link Map.Entry} values.
28+
* If the closure takes two parameters, the key and value are passed separately;
29+
* otherwise the {@link Map.Entry} itself is passed.
30+
*
31+
* @since 6.0.0
32+
*/
33+
public class BooleanClosureForMapPredicate<K, V> implements Predicate<Map.Entry<K, V>> {
34+
private final BooleanClosureWrapper bcw;
35+
private final int numberOfArguments;
36+
37+
public BooleanClosureForMapPredicate(Closure wrapped) {
38+
this.bcw = new BooleanClosureWrapper(wrapped);
39+
this.numberOfArguments = wrapped.getMaximumNumberOfParameters();
40+
}
41+
42+
@Override
43+
public boolean test(Map.Entry<K, V> entry) {
44+
if (numberOfArguments == 2) {
45+
return bcw.call(entry.getKey(), entry.getValue());
46+
} else {
47+
return bcw.call(entry);
48+
}
49+
}
50+
}

src/main/java/org/codehaus/groovy/runtime/callsite/DummyCallSite.java renamed to src/main/java/org/codehaus/groovy/runtime/BooleanClosurePredicate.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,27 @@
1616
* specific language governing permissions and limitations
1717
* under the License.
1818
*/
19-
package org.codehaus.groovy.runtime.callsite;
19+
package org.codehaus.groovy.runtime;
2020

21-
public class DummyCallSite extends AbstractCallSite {
22-
public DummyCallSite(CallSiteArray array, int index, String name) {
23-
super(array, index,name);
21+
import groovy.lang.Closure;
22+
23+
import java.util.function.Predicate;
24+
25+
/**
26+
* Adapts a {@link Closure} to a {@link Predicate}, converting the closure's
27+
* return value to a boolean using Groovy truth semantics.
28+
*
29+
* @since 6.0.0
30+
*/
31+
public class BooleanClosurePredicate<T> implements Predicate<T> {
32+
private final BooleanClosureWrapper bcw;
33+
34+
public BooleanClosurePredicate(Closure wrapped) {
35+
this.bcw = new BooleanClosureWrapper(wrapped);
36+
}
37+
38+
@Override
39+
public boolean test(T arg) {
40+
return bcw.call(arg);
2441
}
2542
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.codehaus.groovy.runtime;
20+
21+
import groovy.lang.Closure;
22+
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
23+
24+
import java.util.Map;
25+
26+
/**
27+
* Helper class for internal use only. This allows calling a {@link Closure} and
28+
* converting the result to a boolean using Groovy truth semantics:
29+
* null returns false, Boolean is unboxed, and for other types
30+
* {@code asBoolean()} is called.
31+
*
32+
* @since 6.0.0
33+
*/
34+
public class BooleanClosureWrapper {
35+
private final Closure wrapped;
36+
private final int numberOfArguments;
37+
38+
public BooleanClosureWrapper(Closure wrapped) {
39+
this.wrapped = wrapped;
40+
this.numberOfArguments = wrapped.getMaximumNumberOfParameters();
41+
}
42+
43+
/**
44+
* Normal closure call with boolean conversion.
45+
*/
46+
public boolean call(Object... args) {
47+
Object result = wrapped.call(args);
48+
if (result == null) return false;
49+
if (result instanceof Boolean) return (Boolean) result;
50+
return DefaultTypeTransformation.castToBoolean(result);
51+
}
52+
53+
/**
54+
* Bridge for a call based on a map entry. If the call is done on a {@link Closure}
55+
* taking one argument, then we give in the {@link Map.Entry}, otherwise we will
56+
* give in the key and value.
57+
*/
58+
public <K, V> boolean callForMap(Map.Entry<K, V> entry) {
59+
if (numberOfArguments == 2) {
60+
return call(entry.getKey(), entry.getValue());
61+
} else {
62+
return call(entry);
63+
}
64+
}
65+
}

src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,9 @@
6363
import org.codehaus.groovy.reflection.MixinInMetaClass;
6464
import org.codehaus.groovy.reflection.ReflectionUtils;
6565
import org.codehaus.groovy.reflection.stdclasses.CachedSAMClass;
66-
import org.codehaus.groovy.runtime.callsite.BooleanClosureForMapPredicate;
67-
import org.codehaus.groovy.runtime.callsite.BooleanClosurePredicate;
68-
import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
69-
import org.codehaus.groovy.runtime.callsite.BooleanReturningMethodInvoker;
66+
import org.codehaus.groovy.runtime.BooleanClosureForMapPredicate;
67+
import org.codehaus.groovy.runtime.BooleanClosurePredicate;
68+
import org.codehaus.groovy.runtime.BooleanClosureWrapper;
7069
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberDiv;
7170
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMinus;
7271
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMultiply;
@@ -574,9 +573,8 @@ public static <T> SortedSet<T> and(SortedSet<T> left, Iterable<T> right, Compara
574573
* @since 1.5.0
575574
*/
576575
public static boolean any(Object self) {
577-
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker();
578576
for (var iter = InvokerHelper.asIterator(self); iter.hasNext(); ) {
579-
if (bmi.convertToBoolean(iter.next())) {
577+
if (DefaultTypeTransformation.castToBoolean(iter.next())) {
580578
return true;
581579
}
582580
}
@@ -5301,9 +5299,8 @@ public static <K, V> boolean every(Map<K, V> self, @ClosureParams(value = MapEnt
53015299
* @since 1.5.0
53025300
*/
53035301
public static boolean every(Object self) {
5304-
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker();
53055302
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); ) {
5306-
if (!bmi.convertToBoolean(iter.next())) {
5303+
if (!DefaultTypeTransformation.castToBoolean(iter.next())) {
53075304
return false;
53085305
}
53095306
}
@@ -7578,10 +7575,9 @@ private static boolean isRootLoaderClassOrSubClass(ClassLoader self) {
75787575
@SuppressWarnings("unchecked")
75797576
public static Collection grep(Object self, Object filter) {
75807577
Collection answer = createSimilarOrDefaultCollection(self);
7581-
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker("isCase");
75827578
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
75837579
Object object = iter.next();
7584-
if (bmi.invoke(filter, object)) {
7580+
if (DefaultTypeTransformation.castToBoolean(InvokerHelper.invokeMethod(filter, "isCase", object))) {
75857581
answer.add(object);
75867582
}
75877583
}
@@ -7609,9 +7605,8 @@ public static Collection grep(Object self, Object filter) {
76097605
*/
76107606
public static <T> Collection<T> grep(Collection<T> self, Object filter) {
76117607
Collection<T> answer = createSimilarCollection(self);
7612-
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker("isCase");
76137608
for (T element : self) {
7614-
if (bmi.invoke(filter, element)) {
7609+
if (DefaultTypeTransformation.castToBoolean(InvokerHelper.invokeMethod(filter, "isCase", element))) {
76157610
answer.add(element);
76167611
}
76177612
}

src/main/java/org/codehaus/groovy/runtime/IOGroovyMethods.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import groovy.transform.stc.PickFirstResolver;
2929
import groovy.transform.stc.SimpleType;
3030
import org.apache.groovy.io.StringBuilderWriter;
31-
import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
31+
import org.codehaus.groovy.runtime.BooleanClosureWrapper;
3232

3333
import java.io.BufferedReader;
3434
import java.io.BufferedWriter;

src/main/java/org/codehaus/groovy/runtime/ResourceGroovyMethods.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import groovy.transform.stc.PickFirstResolver;
3232
import groovy.transform.stc.SimpleType;
3333
import groovy.util.CharsetToolkit;
34-
import org.codehaus.groovy.runtime.callsite.BooleanReturningMethodInvoker;
3534
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
3635

3736
import java.io.BufferedInputStream;
@@ -1651,12 +1650,11 @@ public static void eachFileMatch(final File self, final FileType fileType, final
16511650
final File[] files = self.listFiles();
16521651
// null check because of http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4803836
16531652
if (files == null) return;
1654-
BooleanReturningMethodInvoker bmi = new BooleanReturningMethodInvoker("isCase");
16551653
for (final File currentFile : files) {
16561654
if (fileType == FileType.ANY ||
16571655
(fileType != FileType.FILES && currentFile.isDirectory()) ||
16581656
(fileType != FileType.DIRECTORIES && currentFile.isFile())) {
1659-
if (bmi.invoke(nameFilter, currentFile.getName()))
1657+
if (DefaultTypeTransformation.castToBoolean(InvokerHelper.invokeMethod(nameFilter, "isCase", currentFile.getName())))
16601658
closure.call(currentFile);
16611659
}
16621660
}

src/main/java/org/codehaus/groovy/runtime/callsite/BooleanClosureForMapPredicate.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
import java.util.function.Predicate;
2525

2626
/**
27-
* Helper class for internal use only.
28-
* This creates a Predicate by calling a {@link Closure} and converting the result to a boolean.
29-
* {@link BooleanReturningMethodInvoker} is used for caching.
27+
* @deprecated Use {@link org.codehaus.groovy.runtime.BooleanClosureForMapPredicate} instead.
3028
*/
29+
@Deprecated(since = "6.0.0", forRemoval = true)
30+
@SuppressWarnings("removal")
3131
public class BooleanClosureForMapPredicate<K, V> implements Predicate<Map.Entry<K, V>> {
3232
private final BooleanReturningMethodInvoker bmi;
3333
private final Closure wrapped;
@@ -39,21 +39,12 @@ public BooleanClosureForMapPredicate(Closure wrapped) {
3939
numberOfArguments = wrapped.getMaximumNumberOfParameters();
4040
}
4141

42-
private boolean call(Object... args) {
43-
return bmi.invoke(wrapped, args);
44-
}
45-
46-
/**
47-
* If the call to the backing {@link Closure} is done on a {@link Closure}
48-
* taking one argument, then we give in the {@link Map.Entry}, otherwise we will
49-
* give in the key and value.
50-
*/
5142
@Override
5243
public boolean test(Map.Entry<K, V> entry) {
5344
if (numberOfArguments == 2) {
54-
return call(entry.getKey(), entry.getValue());
45+
return bmi.invoke(wrapped, entry.getKey(), entry.getValue());
5546
} else {
56-
return call(entry);
47+
return bmi.invoke(wrapped, entry);
5748
}
5849
}
5950
}

src/main/java/org/codehaus/groovy/runtime/callsite/BooleanClosurePredicate.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323
import java.util.function.Predicate;
2424

2525
/**
26-
* Helper class for internal use only.
27-
* This creates a Predicate by calling a {@link Closure} and converting the result to a boolean.
28-
* {@link BooleanReturningMethodInvoker} is used for caching.
26+
* @deprecated Use {@link org.codehaus.groovy.runtime.BooleanClosurePredicate} instead.
2927
*/
28+
@Deprecated(since = "6.0.0", forRemoval = true)
29+
@SuppressWarnings("removal")
3030
public class BooleanClosurePredicate<T> implements Predicate<T> {
3131
private final BooleanReturningMethodInvoker bmi;
3232
private final Closure wrapped;

0 commit comments

Comments
 (0)