Groovy example source code file (DefaultGroovyMethods.java)
This example Groovy source code file (DefaultGroovyMethods.java) is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.
/*
* Copyright 2003-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.runtime;
import groovy.io.EncodingAwareBufferedWriter;
import groovy.io.FileType;
import groovy.io.FileVisitResult;
import groovy.io.GroovyPrintWriter;
import groovy.lang.*;
import groovy.util.*;
import org.codehaus.groovy.classgen.Verifier;
import org.codehaus.groovy.reflection.ClassInfo;
import org.codehaus.groovy.reflection.MixinInMetaClass;
import org.codehaus.groovy.reflection.ReflectionCache;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberDiv;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMinus;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMultiply;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberPlus;
import org.codehaus.groovy.runtime.dgmimpl.arrays.*;
import org.codehaus.groovy.runtime.metaclass.ClosureMetaClass;
import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.codehaus.groovy.runtime.typehandling.GroovyCastException;
import org.codehaus.groovy.runtime.typehandling.NumberMath;
import org.codehaus.groovy.tools.RootLoader;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This class defines new groovy methods which appear on normal JDK
* classes inside the Groovy environment. Static methods are used with the
* first parameter being the destination class,
* i.e. <code>public static String reverse(String self)
* provides a <code>reverse() method for String.
* <p>
* NOTE: While this class contains many 'public' static methods, it is
* primarily regarded as an internal class (its internal package name
* suggests this also). We value backwards compatibility of these
* methods when used within Groovy but value less backwards compatibility
* at the Java method call level. I.e. future versions of Groovy may
* remove or move a method call in this file but would normally
* aim to keep the method available from within Groovy.
*
* @author <a href="mailto:james@coredevelopers.net">James Strachan
* @author Jeremy Rayner
* @author Sam Pullara
* @author Rod Cope
* @author Guillaume Laforge
* @author John Wilson
* @author Hein Meling
* @author Dierk Koenig
* @author Pilho Kim
* @author Marc Guillemot
* @author Russel Winder
* @author bing ran
* @author Jochen Theodorou
* @author Paul King
* @author Michael Baehr
* @author Joachim Baumann
* @author Alex Tkachman
* @author Ted Naleid
* @author Brad Long
* @author Jim Jagielski
* @author Rodolfo Velasco
* @author jeremi Joslin
* @author Hamlet D'Arcy
* @author Cedric Champeau
* @author Tim Yates
* @author Dinko Srkoc
*/
public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
private static final Logger LOG = Logger.getLogger(DefaultGroovyMethods.class.getName());
private static final Integer ONE = 1;
private static final BigInteger BI_INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
private static final BigInteger BI_INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE);
private static final BigInteger BI_LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
private static final BigInteger BI_LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE);
public static final Class [] additionals = {
NumberNumberPlus.class,
NumberNumberMultiply.class,
NumberNumberMinus.class,
NumberNumberDiv.class,
ObjectArrayGetAtMetaMethod.class,
ObjectArrayPutAtMetaMethod.class,
BooleanArrayGetAtMetaMethod.class,
BooleanArrayPutAtMetaMethod.class,
ByteArrayGetAtMetaMethod.class,
ByteArrayPutAtMetaMethod.class,
CharacterArrayGetAtMetaMethod.class,
CharacterArrayPutAtMetaMethod.class,
ShortArrayGetAtMetaMethod.class,
ShortArrayPutAtMetaMethod.class,
IntegerArrayGetAtMetaMethod.class,
IntegerArrayPutAtMetaMethod.class,
LongArrayGetAtMetaMethod.class,
LongArrayPutAtMetaMethod.class,
FloatArrayGetAtMetaMethod.class,
FloatArrayPutAtMetaMethod.class,
DoubleArrayGetAtMetaMethod.class,
DoubleArrayPutAtMetaMethod.class,
};
/**
* Identity check. Since == is overridden in Groovy with the meaning of equality
* we need some fallback to check for object identity. Invoke using the
* 'is' method, like so: <code>def same = this.is(that)
*
* @param self an object
* @param other an object to compare identity with
* @return true if self and other are both references to the same
* instance, false otherwise
* @since 1.0
*/
public static boolean is(Object self, Object other) {
return self == other;
}
/**
* Allows the closure to be called for the object reference self.
* Synonym for 'with()'.
*
* @param self the object to have a closure act upon
* @param closure the closure to call on the object
* @return result of calling the closure
* @since 1.0
*/
public static <T> T identity(Object self, Closure closure) {
return DefaultGroovyMethods.with(self, closure);
}
/**
* Allows the closure to be called for the object reference self. <br/>
* Any method invoked inside the closure will first be invoked on the
* self reference. For instance, the following method calls to the append()
* method are invoked on the StringBuilder instance:
* <pre>
* def b = new StringBuilder().with {
* append('foo')
* append('bar')
* return it
* }
* assert b.toString() == 'foobar'
* </pre>
* This is commonly used to simplify object creation, such as this example:
* <pre>
* def p = new Person().with {
* firstName = 'John'
* lastName = 'Doe'
* return it
* }
* </pre>
*
* @param self the object to have a closure act upon
* @param closure the closure to call on the object
* @return result of calling the closure
* @since 1.5.0
*/
public static <T> T with(Object self, Closure closure) {
@SuppressWarnings("unchecked")
final Closure<T> clonedClosure = (Closure) closure.clone();
clonedClosure.setResolveStrategy(Closure.DELEGATE_FIRST);
clonedClosure.setDelegate(self);
return clonedClosure.call(self);
}
/**
* Allows the subscript operator to be used to lookup dynamic property values.
* <code>bean[somePropertyNameExpression]. The normal property notation
* of groovy is neater and more concise but only works with compile-time known
* property names.
*
* @param self the object to act upon
* @param property the property name of interest
* @return the property value
* @since 1.0
*/
public static Object getAt(Object self, String property) {
return InvokerHelper.getProperty(self, property);
}
/**
* Allows the subscript operator to be used to set dynamically named property values.
* <code>bean[somePropertyNameExpression] = foo. The normal property notation
* of groovy is neater and more concise but only works with property names which
* are known at compile time.
*
* @param self the object to act upon
* @param property the name of the property to set
* @param newValue the value to set
* @since 1.0
*/
public static void putAt(Object self, String property, Object newValue) {
InvokerHelper.setProperty(self, property, newValue);
}
/**
* Generates a detailed dump string of an object showing its class,
* hashCode and fields.
*
* @param self an object
* @return the dump representation
* @since 1.0
*/
public static String dump(Object self) {
if (self == null) {
return "null";
}
StringBuilder buffer = new StringBuilder("<");
Class klass = self.getClass();
buffer.append(klass.getName());
buffer.append("@");
buffer.append(Integer.toHexString(self.hashCode()));
boolean groovyObject = self instanceof GroovyObject;
/*jes this may be rewritten to use the new getProperties() stuff
* but the original pulls out private variables, whereas getProperties()
* does not. What's the real use of dump() here?
*/
while (klass != null) {
for (final Field field : klass.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.STATIC) == 0) {
if (groovyObject && field.getName().equals("metaClass")) {
continue;
}
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
field.setAccessible(true);
return null;
}
});
buffer.append(" ");
buffer.append(field.getName());
buffer.append("=");
try {
buffer.append(InvokerHelper.toString(field.get(self)));
} catch (Exception e) {
buffer.append(e);
}
}
}
klass = klass.getSuperclass();
}
/* here is a different implementation that uses getProperties(). I have left
* it commented out because it returns a slightly different list of properties;
* i.e. it does not return privates. I don't know what dump() really should be doing,
* although IMO showing private fields is a no-no
*/
/*
List props = getProperties(self);
for(Iterator itr = props.keySet().iterator(); itr.hasNext(); ) {
String propName = itr.next().toString();
// the original skipped this, so I will too
if(pv.getName().equals("class")) continue;
if(pv.getName().equals("metaClass")) continue;
buffer.append(" ");
buffer.append(propName);
buffer.append("=");
try {
buffer.append(InvokerHelper.toString(props.get(propName)));
}
catch (Exception e) {
buffer.append(e);
}
}
*/
buffer.append(">");
return buffer.toString();
}
/**
* Retrieves the list of {@link groovy.lang.MetaProperty} objects for 'self' and wraps it
* in a list of {@link groovy.lang.PropertyValue} objects that additionally provide
* the value for each property of 'self'.
*
* @param self the receiver object
* @return list of {@link groovy.lang.PropertyValue} objects
* @see groovy.util.Expando#getMetaPropertyValues()
* @since 1.0
*/
public static List<PropertyValue> getMetaPropertyValues(Object self) {
MetaClass metaClass = InvokerHelper.getMetaClass(self);
List<MetaProperty> mps = metaClass.getProperties();
List<PropertyValue> props = new ArrayList(mps.size());
for (MetaProperty mp : mps) {
props.add(new PropertyValue(self, mp));
}
return props;
}
/**
* Convenience method that calls {@link #getMetaPropertyValues(java.lang.Object)}(self)
* and provides the data in form of simple key/value pairs, i.e.&nsbp;without
* type() information.
*
* @param self the receiver object
* @return meta properties as Map of key/value pairs
* @since 1.0
*/
public static Map getProperties(Object self) {
List<PropertyValue> metaProps = getMetaPropertyValues(self);
Map<String, Object> props = new LinkedHashMap(metaProps.size());
for (PropertyValue mp : metaProps) {
try {
props.put(mp.getName(), mp.getValue());
} catch (Exception e) {
LOG.throwing(self.getClass().getName(), "getProperty(" + mp.getName() + ")", e);
}
}
return props;
}
/**
* Scoped use method
*
* @param self any Object
* @param categoryClass a category class to use
* @param closure the closure to invoke with the category in place
* @return the value returned from the closure
* @since 1.0
*/
public static <T> T use(Object self, Class categoryClass, Closure closure) {
return GroovyCategorySupport.use(categoryClass, closure);
}
/**
* Extend object with category methods.
* All methods for given class and all super classes will be added to the object.
*
* @param self any Class
* @param categoryClasses a category classes to use
* @since 1.6.0
*/
public static void mixin(MetaClass self, List<Class> categoryClasses) {
MixinInMetaClass.mixinClassesToMetaClass(self, categoryClasses);
}
/**
* Extend class globally with category methods.
* All methods for given class and all super classes will be added to the class.
*
* @param self any Class
* @param categoryClasses a category classes to use
* @since 1.6.0
*/
public static void mixin(Class self, List<Class> categoryClasses) {
mixin(getMetaClass(self), categoryClasses);
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(Class self, Class categoryClass) {
mixin(getMetaClass(self), Collections.singletonList(categoryClass));
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(Class self, Class[] categoryClass) {
mixin(getMetaClass(self), Arrays.asList(categoryClass));
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(MetaClass self, Class categoryClass) {
mixin(self, Collections.singletonList(categoryClass));
}
/**
* Extend class globally with category methods.
*
* @param self any Class
* @param categoryClass a category class to use
* @since 1.6.0
*/
public static void mixin(MetaClass self, Class[] categoryClass) {
mixin(self, Arrays.asList(categoryClass));
}
/**
* Scoped use method with list of categories.
*
* @param self any Object
* @param categoryClassList a list of category classes
* @param closure the closure to invoke with the categories in place
* @return the value returned from the closure
* @since 1.0
*/
public static <T> T use(Object self, List categoryClassList, Closure closure) {
return GroovyCategorySupport.use(categoryClassList, closure);
}
/**
* Allows the usage of addShutdownHook without getting the runtime first.
*
* @param self the object the method is called on (ignored)
* @param closure the shutdown hook action
* @since 1.5.0
*/
public static void addShutdownHook(Object self, Closure closure) {
Runtime.getRuntime().addShutdownHook(new Thread(closure));
}
/**
* Allows you to use a list of categories, specifying the list as varargs.
* <code>use(CategoryClass1, CategoryClass2) { ... }
* This method saves having to wrap the the category
* classes in a list.
*
* @param self any Object
* @param array a list of category classes and a Closure
* @return the value returned from the closure
* @since 1.0
*/
public static Object use(Object self, Object[] array) {
if (array.length < 2)
throw new IllegalArgumentException(
"Expecting at least 2 arguments, a category class and a Closure");
Closure closure;
try {
closure = (Closure) array[array.length - 1];
} catch (ClassCastException e) {
throw new IllegalArgumentException("Expecting a Closure to be the last argument");
}
List<Class> list = new ArrayList(array.length - 1);
for (int i = 0; i < array.length - 1; ++i) {
Class categoryClass;
try {
categoryClass = (Class) array[i];
} catch (ClassCastException e) {
throw new IllegalArgumentException("Expecting a Category Class for argument " + i);
}
list.add(categoryClass);
}
return GroovyCategorySupport.use(list, closure);
}
/**
* Print a value formatted Groovy style to self if it
* is a Writer, otherwise to the standard output stream.
*
* @param self any Object
* @param value the value to print
* @since 1.0
*/
public static void print(Object self, Object value) {
// we won't get here if we are a PrintWriter
if (self instanceof Writer) {
try {
((Writer) self).write(InvokerHelper.toString(value));
} catch (IOException e) {
// TODO: Should we have some unified function like PrintWriter.checkError()?
}
} else {
System.out.print(InvokerHelper.toString(value));
}
}
/**
* Print a value formatted Groovy style to the print writer.
*
* @param self a PrintWriter
* @param value the value to print
* @since 1.0
*/
public static void print(PrintWriter self, Object value) {
self.print(InvokerHelper.toString(value));
}
/**
* Print a value formatted Groovy style to the print stream.
*
* @param self a PrintStream
* @param value the value to print
* @since 1.6.0
*/
public static void print(PrintStream self, Object value) {
self.print(InvokerHelper.toString(value));
}
/**
* Print a value to the standard output stream.
* This method delegates to the owner to execute the method.
*
* @param self a generated closure
* @param value the value to print
* @since 1.0
*/
public static void print(Closure self, Object value) {
Object owner = getClosureOwner(self);
InvokerHelper.invokeMethod(owner, "print", new Object[]{value});
}
/**
* Print a linebreak to the standard output stream.
*
* @param self any Object
* @since 1.0
*/
public static void println(Object self) {
// we won't get here if we are a PrintWriter
if (self instanceof Writer) {
PrintWriter pw = new GroovyPrintWriter((Writer) self);
pw.println();
} else {
System.out.println();
}
}
/**
* Print a linebreak to the standard output stream.
* This method delegates to the owner to execute the method.
*
* @param self a closure
* @since 1.0
*/
public static void println(Closure self) {
Object owner = getClosureOwner(self);
InvokerHelper.invokeMethod(owner, "println", new Object[0]);
}
private static Object getClosureOwner(Closure cls) {
Object owner = cls.getOwner();
while (owner instanceof GeneratedClosure) {
owner = ((Closure) owner).getOwner();
}
return owner;
}
/**
* Print a value formatted Groovy style (followed by a newline) to self
* if it is a Writer, otherwise to the standard output stream.
*
* @param self any Object
* @param value the value to print
* @since 1.0
*/
public static void println(Object self, Object value) {
// we won't get here if we are a PrintWriter
if (self instanceof Writer) {
final PrintWriter pw = new GroovyPrintWriter((Writer) self);
pw.println(value);
} else {
System.out.println(InvokerHelper.toString(value));
}
}
/**
* Print a value formatted Groovy style (followed by a newline) to the print writer.
*
* @param self a PrintWriter
* @param value the value to print
* @since 1.0
*/
public static void println(PrintWriter self, Object value) {
self.println(InvokerHelper.toString(value));
}
/**
* Print a value formatted Groovy style (followed by a newline) to the print stream.
*
* @param self any Object
* @param value the value to print
* @since 1.6.0
*/
public static void println(PrintStream self, Object value) {
self.println(InvokerHelper.toString(value));
}
/**
* Print a value (followed by a newline) to the standard output stream.
* This method delegates to the owner to execute the method.
*
* @param self a closure
* @param value the value to print
* @since 1.0
*/
public static void println(Closure self, Object value) {
Object owner = getClosureOwner(self);
InvokerHelper.invokeMethod(owner, "println", new Object[]{value});
}
/**
* Printf to a console (Only works with JDK1.5 or later).
*
* @param self any Object
* @param format a format string
* @param values values referenced by the format specifiers in the format string.
* @since 1.0
*/
public static void printf(Object self, String format, Object[] values) {
if (self instanceof PrintStream)
((PrintStream)self).printf(format, values);
else
System.out.printf(format, values);
}
/**
* Sprintf to a string (Only works with JDK1.5 or later).
*
* @param self any Object
* @param format a format string
* @param values values referenced by the format specifiers in the format string.
* @return the resulting formatted string
* @since 1.5.0
*/
public static String sprintf(Object self, String format, Object[] values) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PrintStream out = new PrintStream(outputStream);
out.printf(format, values);
return outputStream.toString();
}
/**
* Prints a formatted string using the specified format string and
* arguments.
* <p/>
* For examples, <pre>
* printf ( "Hello, %s!\n" , [ "world" ] as String[] )
* printf ( "Hello, %s!\n" , [ "Groovy" ])
* printf ( "%d + %d = %d\n" , [ 1 , 2 , 1+2 ] as Integer[] )
* printf ( "%d + %d = %d\n" , [ 3 , 3 , 3+3 ])
* <p/>
* ( 1..5 ).each { printf ( "-- %d\n" , [ it ] as Integer[] ) }
* ( 1..5 ).each { printf ( "-- %d\n" , [ it ] as int[] ) }
* ( 0x41..0x45 ).each { printf ( "-- %c\n" , [ it ] as char[] ) }
* ( 07..011 ).each { printf ( "-- %d\n" , [ it ] as byte[] ) }
* ( 7..11 ).each { printf ( "-- %d\n" , [ it ] as short[] ) }
* ( 7..11 ).each { printf ( "-- %d\n" , [ it ] as long[] ) }
* ( 7..11 ).each { printf ( "-- %5.2f\n" , [ it ] as float[] ) }
* ( 7..11 ).each { printf ( "-- %5.2g\n" , [ it ] as double[] ) }
* </pre>
* <p/>
*
* @param self any Object
* @param format A format string
* @param arg Argument which is referenced by the format specifiers in the format
* string. The type of <code>arg should be one of Object[], List,
* int[], short[], byte[], char[], boolean[], long[], float[], or double[].
* @since 1.0
*/
public static void printf(Object self, String format, Object arg) {
if (self instanceof PrintStream)
printf((PrintStream) self, format, arg);
else if (self instanceof Writer)
printf((Writer) self, format, arg);
else
printf(System.out, format, arg);
}
private static void printf(PrintStream self, String format, Object arg) {
self.print(sprintf(self, format, arg));
}
private static void printf(Writer self, String format, Object arg) {
try {
self.write(sprintf(self, format, arg));
} catch (IOException e) {
printf(System.out, format, arg);
}
}
/**
* Returns a formatted string using the specified format string and
* arguments.
* <p/>
*
* @param self any Object
* @param format A format string
* @param arg Argument which is referenced by the format specifiers in the format
* string. The type of <code>arg should be one of Object[], List,
* int[], short[], byte[], char[], boolean[], long[], float[], or double[].
* @return the resulting printf'd string
* @since 1.5.0
*/
public static String sprintf(Object self, String format, Object arg) {
if (arg instanceof Object[]) {
return sprintf(self, format, (Object[]) arg);
}
if (arg instanceof List) {
return sprintf(self, format, ((List) arg).toArray());
}
if (!arg.getClass().isArray()) {
Object[] o = (Object[]) java.lang.reflect.Array.newInstance(arg.getClass(), 1);
o[0] = arg;
return sprintf(self, format, o);
}
Object[] ans;
String elemType = arg.getClass().getName();
if (elemType.equals("[I")) {
int[] ia = (int[]) arg;
ans = new Integer[ia.length];
for (int i = 0; i < ia.length; i++) {
ans[i] = ia[i];
}
} else if (elemType.equals("[C")) {
char[] ca = (char[]) arg;
ans = new Character[ca.length];
for (int i = 0; i < ca.length; i++) {
ans[i] = ca[i];
}
} else if (elemType.equals("[Z")) {
boolean[] ba = (boolean[]) arg;
ans = new Boolean[ba.length];
for (int i = 0; i < ba.length; i++) {
ans[i] = ba[i];
}
} else if (elemType.equals("[B")) {
byte[] ba = (byte[]) arg;
ans = new Byte[ba.length];
for (int i = 0; i < ba.length; i++) {
ans[i] = ba[i];
}
} else if (elemType.equals("[S")) {
short[] sa = (short[]) arg;
ans = new Short[sa.length];
for (int i = 0; i < sa.length; i++) {
ans[i] = sa[i];
}
} else if (elemType.equals("[F")) {
float[] fa = (float[]) arg;
ans = new Float[fa.length];
for (int i = 0; i < fa.length; i++) {
ans[i] = fa[i];
}
} else if (elemType.equals("[J")) {
long[] la = (long[]) arg;
ans = new Long[la.length];
for (int i = 0; i < la.length; i++) {
ans[i] = la[i];
}
} else if (elemType.equals("[D")) {
double[] da = (double[]) arg;
ans = new Double[da.length];
for (int i = 0; i < da.length; i++) {
ans[i] = da[i];
}
} else {
throw new RuntimeException("sprintf(String," + arg + ")");
}
return sprintf(self, format, ans);
}
/**
* Inspects returns the String that matches what would be typed into a
* terminal to create this object.
*
* @param self any Object
* @return a String that matches what would be typed into a terminal to
* create this object. e.g. [1, 'hello'].inspect() -> [1, "hello"]
* @since 1.0
*/
public static String inspect(Object self) {
return InvokerHelper.inspect(self);
}
/**
* Print to a console in interactive format.
*
* @param self any Object
* @param out the PrintWriter used for printing
* @since 1.0
*/
public static void print(Object self, PrintWriter out) {
if (out == null) {
out = new PrintWriter(System.out);
}
out.print(InvokerHelper.toString(self));
}
/**
* Print to a console in interactive format.
*
* @param self any Object
* @param out the PrintWriter used for printing
* @since 1.0
*/
public static void println(Object self, PrintWriter out) {
if (out == null) {
out = new PrintWriter(System.out);
}
out.println(InvokerHelper.toString(self));
}
/**
* Provide a dynamic method invocation method which can be overloaded in
* classes to implement dynamic proxies easily.
*
* @param object any Object
* @param method the name of the method to call
* @param arguments the arguments to use
* @return the result of the method call
* @since 1.0
*/
public static Object invokeMethod(Object object, String method, Object arguments) {
return InvokerHelper.invokeMethod(object, method, arguments);
}
// isCase methods
//-------------------------------------------------------------------------
/**
* Method for overloading the behavior of the 'case' method in switch statements.
* The default implementation handles arrays types but otherwise simply delegates
* to Object#equals, but this may be overridden for other types. In this example:
* <pre> switch( a ) {
* case b: //some code
* }</pre>
* "some code" is called when <code>b.isCase( a ) returns
* <code>true.
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue is deemed to be equal to the caseValue
* @since 1.0
*/
public static boolean isCase(Object caseValue, Object switchValue) {
if (caseValue.getClass().isArray()) {
return isCase(DefaultTypeTransformation.asCollection(caseValue), switchValue);
}
return caseValue.equals(switchValue);
}
/**
* 'Case' implementation for a String, which uses String#equals(Object)
* in order to allow Strings to be used in switch statements.
* For example:
* <pre>switch( str ) {
* case 'one' :
* // etc...
* }</pre>
* Note that this returns <code>true for the case where both the
* 'switch' and 'case' operand is <code>null.
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue's toString() equals the caseValue
* @since 1.0
*/
public static boolean isCase(String caseValue, Object switchValue) {
if (switchValue == null) {
return caseValue == null;
}
return caseValue.equals(switchValue.toString());
}
/**
* 'Case' implementation for a GString, which simply calls the equivalent method for String.
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue's toString() equals the caseValue
* @since 1.6.0
*/
public static boolean isCase(GString caseValue, Object switchValue) {
return isCase(caseValue.toString(), switchValue);
}
/**
* Special 'Case' implementation for Class, which allows testing
* for a certain class in a switch statement.
* For example:
* <pre>switch( obj ) {
* case List :
* // obj is a list
* break;
* case Set :
* // etc
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue is deemed to be assignable from the given class
* @since 1.0
*/
public static boolean isCase(Class caseValue, Object switchValue) {
if (switchValue instanceof Class) {
Class val = (Class) switchValue;
return caseValue.isAssignableFrom(val);
}
return caseValue.isInstance(switchValue);
}
/**
* 'Case' implementation for collections which tests if the 'switch'
* operand is contained in any of the 'case' values.
* For example:
* <pre class="groovyTestCase">switch( 3 ) {
* case [1,3,5]:
* assert true
* break
* default:
* assert false
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the caseValue is deemed to contain the switchValue
* @see java.util.Collection#contains(java.lang.Object)
* @since 1.0
*/
public static boolean isCase(Collection caseValue, Object switchValue) {
return caseValue.contains(switchValue);
}
/**
* 'Case' implementation for maps which tests the groovy truth
* value obtained using the 'switch' operand as key.
* For example:
* <pre class="groovyTestCase">switch( 'foo' ) {
* case [foo:true, bar:false]:
* assert true
* break
* default:
* assert false
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return the groovy truth value from caseValue corresponding to the switchValue key
* @since 1.7.6
*/
public static boolean isCase(Map caseValue, Object switchValue) {
return DefaultTypeTransformation.castToBoolean(caseValue.get(switchValue));
}
/**
* 'Case' implementation for the {@link java.util.regex.Pattern} class, which allows
* testing a String against a number of regular expressions.
* For example:
* <pre>switch( str ) {
* case ~/one/ :
* // the regex 'one' matches the value of str
* }
* </pre>
* Note that this returns true for the case where both the pattern and
* the 'switch' values are <code>null.
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue is deemed to match the caseValue
* @since 1.0
*/
public static boolean isCase(Pattern caseValue, Object switchValue) {
if (switchValue == null) {
return caseValue == null;
}
final Matcher matcher = caseValue.matcher(switchValue.toString());
if (matcher.matches()) {
RegexSupport.setLastMatcher(matcher);
return true;
} else {
return false;
}
}
/**
* Special 'case' implementation for all numbers, which delegates to the
* <code>compareTo() method for comparing numbers of different
* types.
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the numbers are deemed equal
* @since 1.5.0
*/
public static boolean isCase(Number caseValue, Number switchValue) {
return NumberMath.compareTo(caseValue, switchValue) == 0;
}
/**
* Returns an iterator equivalent to this iterator all duplicated items removed
* by using the default comparator. The original iterator will become
* exhausted of elements after determining the unique values. A new iterator
* for the unique values will be returned.
*
* @param self an Iterator
* @return the modified Iterator
* @since 1.5.5
*/
public static <T> Iterator unique(Iterator self) {
return toList(unique(toList(self))).listIterator();
}
/**
* Modifies this collection to remove all duplicated items, using the
* default comparator.
* <pre class="groovyTestCase">assert [1,3] == [1,3,3].unique()
*
* @param self a collection
* @return the now modified collection
* @see #unique(Collection, boolean)
* @since 1.0
*/
public static <T> Collection unique(Collection self) {
return unique(self, true);
}
/**
* Remove all duplicates from a given Collection using the default comparator.
* If mutate is true, it works by modifying the original object (and also returning it).
* If mutate is false, a new collection is returned leaving the original unchanged.
* <pre class="groovyTestCase">
* assert [1,3] == [1,3,3].unique()
* </pre>
* <pre class="groovyTestCase">
* def orig = [1, 3, 2, 3]
* def uniq = orig.unique(false)
* assert orig == [1, 3, 2, 3]
* assert uniq == [1, 3, 2]
* </pre>
*
* @param self a collection
* @param mutate false will cause a new list containing unique items from the collection to be created, true will mutate collections in place
* @return the now modified collection
* @since 1.8.1
*/
public static <T> Collection unique(Collection self, boolean mutate) {
List<T> answer = new ArrayList();
for (T t : self) {
boolean duplicated = false;
for (T t2 : answer) {
if (coercedEquals(t, t2)) {
duplicated = true;
break;
}
}
if (!duplicated)
answer.add(t);
}
if (mutate) {
self.clear();
self.addAll(answer);
}
return mutate ? self : answer ;
}
/**
* Provides a method that compares two comparables using Groovy's
* default number aware comparator.
*
* @param self a Comparable
* @param other another Comparable
* @return a -ve number, 0 or a +ve number according to Groovy's compareTo contract
* @since 1.6.0
*/
public static int numberAwareCompareTo(Comparable self, Comparable other) {
NumberAwareComparator<Comparable> numberAwareComparator = new NumberAwareComparator();
return numberAwareComparator.compare(self, other);
}
/**
* Returns an iterator equivalent to this iterator but with all duplicated items
* removed by using a Closure to determine duplicate (equal) items.
* The original iterator will be fully processed after the call.
* </p>
* If the closure takes a
* single parameter, the argument passed will be each element, and the
* closure should return a value used for comparison (either using
* {@link java.lang.Comparable#compareTo(java.lang.Object)} or {@link java.lang.Object#equals(java.lang.Object)}).
* If the closure takes two parameters, two items from the Iterator
* will be passed as arguments, and the closure should return an
* int value (with 0 indicating the items are not unique).
*
* @param self an Iterator
* @param closure a Closure used to determine unique items
* @return the modified Iterator
* @since 1.5.5
*/
public static <T> Iterator unique(Iterator self, Closure closure) {
return toList(unique(toList(self), closure)).listIterator();
}
/**
* A convenience method for making a collection unique using a Closure
* to determine duplicate (equal) items.
* </p>
* If the closure takes a single parameter, the
* argument passed will be each element, and the closure
* should return a value used for comparison (either using
* {@link java.lang.Comparable#compareTo(java.lang.Object)} or {@link java.lang.Object#equals(java.lang.Object)}).
* If the closure takes two parameters, two items from the collection
* will be passed as arguments, and the closure should return an
* int value (with 0 indicating the items are not unique).
* <pre class="groovyTestCase">assert [1,4] == [1,3,4,5].unique { it % 2 }
* <pre class="groovyTestCase">assert [2,3,4] == [2,3,3,4].unique { a, b -> a <=> b }
*
* @param self a Collection
* @param closure a 1 or 2 arg Closure used to determine unique items
* @return self without any duplicates
* @see #unique(Collection, boolean, Closure)
* @since 1.0
*/
public static <T> Collection unique(Collection self, Closure closure) {
return unique(self, true, closure);
}
/**
* A convenience method for making a collection unique using a Closure to determine duplicate (equal) items.
* If mutate is true, it works on the receiver object and returns it. If mutate is false, a new collection is returned.
* </p>
* If the closure takes a single parameter, the
* argument passed will be each element, and the closure
* should return a value used for comparison (either using
* {@link java.lang.Comparable#compareTo(java.lang.Object)} or {@link java.lang.Object#equals(java.lang.Object)}).
* If the closure takes two parameters, two items from the collection
* will be passed as arguments, and the closure should return an
* int value (with 0 indicating the items are not unique).
* <pre class="groovyTestCase">
* def orig = [1, 3, 4, 5]
* def uniq = orig.unique(false) { it % 2 }
* assert orig == [1, 3, 4, 5]
* assert uniq == [1, 4]
* </pre>
* <pre class="groovyTestCase">
* def orig = [2, 3, 3, 4]
* def uniq = orig.unique(false) { a, b -> a <=> b }
* assert orig == [2, 3, 3, 4]
* assert uniq == [2, 3, 4]
* </pre>
*
* @param self a Collection
* @param mutate false will always cause a new list to be created, true will mutate lists in place
* @param closure a 1 or 2 arg Closure used to determine unique items
* @return self without any duplicates
* @since 1.8.1
*/
public static <T> Collection unique(Collection self, boolean mutate, Closure closure) {
// use a comparator of one item or two
int params = closure.getMaximumNumberOfParameters();
if (params == 1) {
OrderBy<T> by = new OrderBy(closure);
by.setEqualityCheck(true);
self = unique(self, mutate, by);
} else {
self = unique(self, mutate, new ClosureComparator<T>(closure));
}
return self;
}
/**
* Returns an iterator equivalent to this iterator with all duplicated
* items removed by using the supplied comparator.
*
* @param self an Iterator
* @param comparator a Comparator
* @return the modified Iterator
* @since 1.5.5
*/
public static <T> Iterator unique(Iterator self, Comparator comparator) {
return toList(unique(toList(self), comparator)).listIterator();
}
/**
* Remove all duplicates from a given Collection.
* Works on the original object (and also returns it).
* The order of members in the Collection are compared by the given Comparator.
* For each duplicate, the first member which is returned
* by the given Collection's iterator is retained, but all other ones are removed.
* The given Collection's original order is preserved.
* <p/>
* <code>
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.unique(new PersonComparator())
* assert( list2 == list && list == [a, b, c] )
* </pre>
*
* @param self a Collection
* @param comparator a Comparator
* @return self the now modified collection without duplicates
* @see #unique(java.util.Collection, boolean, java.util.Comparator)
* @since 1.0
*/
public static <T> Collection unique(Collection self, Comparator comparator) {
return unique(self, true, comparator) ;
}
/**
* Remove all duplicates from a given Collection.
* If mutate is true, it works on the original object (and also returns it). If mutate is false, a new collection is returned.
* The order of members in the Collection are compared by the given Comparator.
* For each duplicate, the first member which is returned
* by the given Collection's iterator is retained, but all other ones are removed.
* The given Collection's original order is preserved.
* <p/>
* <code>
* class Person {
* def fname, lname
* String toString() {
* return fname + " " + lname
* }
* }
*
* class PersonComparator implements Comparator {
* int compare(Object o1, Object o2) {
* Person p1 = (Person) o1
* Person p2 = (Person) o2
* if (p1.lname != p2.lname)
* return p1.lname.compareTo(p2.lname)
* else
* return p1.fname.compareTo(p2.fname)
* }
*
* boolean equals(Object obj) {
* return this.equals(obj)
* }
* }
*
* Person a = new Person(fname:"John", lname:"Taylor")
* Person b = new Person(fname:"Clark", lname:"Taylor")
* Person c = new Person(fname:"Tom", lname:"Cruz")
* Person d = new Person(fname:"Clark", lname:"Taylor")
*
* def list = [a, b, c, d]
* List list2 = list.unique(false, new PersonComparator())
* assert( list2 != list && list2 == [a, b, c] )
* </pre>
*
*
* @param self a Collection
* @param mutate false will always cause a new collection to be created, true will mutate collections in place
* @param comparator a Comparator
* @return self the collection without duplicates
* @since 1.8.1
*/
public static <T> Collection unique(Collection self, boolean mutate, Comparator comparator) {
List<T> answer = new ArrayList();
for (T t : self) {
boolean duplicated = false;
for (T t2 : answer) {
if (comparator.compare(t, t2) == 0) {
duplicated = true;
break;
}
}
if (!duplicated)
answer.add(t);
}
if (mutate) {
self.clear();
self.addAll(answer);
}
return mutate ? self : answer;
}
/**
* Iterates through an aggregate type or data structure,
* passing each item to the given closure. Custom types may utilize this
* method by simply providing an "iterator()" method. The items returned
* from the resulting iterator will be passed to the closure.
*
* @param self the object over which we iterate
* @param closure the closure applied on each element found
* @return the self Object
* @since 1.0
*/
public static <T> T each(T self, Closure closure) {
each(InvokerHelper.asIterator(self), closure);
return self;
}
/**
* Iterates through an aggregate type or data structure,
* passing each item and the item's index (a counter starting at
* zero) to the given closure.
*
* @param self an Object
* @param closure a Closure to operate on each item
* @return the self Object
* @since 1.0
*/
public static <T> T eachWithIndex(T self, Closure closure) {
final Object[] args = new Object[2];
int counter = 0;
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
args[0] = iter.next();
args[1] = counter++;
closure.call(args);
}
return self;
}
private static <T> Iterator each(Iterator iter, Closure closure) {
final Object[] args = new Object[1];
final Class[] types = new Class[1];
MetaClass mc = closure.getMetaClass();
MetaMethod cachedMethod = null;
Class cachedType = null;
while (iter.hasNext()) {
Object arg = iter.next();
args[0] = arg;
Class type = null;
if (arg!=null) type = arg.getClass();
if (cachedMethod==null || type!=cachedType) {
types[0] = type;
cachedMethod = mc.pickMethod("call", types);
cachedType = type;
}
if (cachedMethod!=null) {
cachedMethod.doMethodInvoke(closure, args);
} else {
mc.invokeMethod(closure, "call", args);
}
}
return iter;
}
/**
* Allows a Map to be iterated through using a closure. If the
* closure takes one parameter then it will be passed the Map.Entry
* otherwise if the closure takes two parameters then it will be
* passed the key and the value.
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].each { key, value -> result += "$key$value" }
* assert result == "a1b3"</pre>
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].each { entry -> result += entry }
* assert result == "a=1b=3"</pre>
*
* In general, the order in which the map contents are processed
* cannot be guaranteed. In practise, specialized forms of Map,
* e.g. a TreeMap will have its contents processed according to
* the natural ordering of the map.
*
* @param self the map over which we iterate
* @param closure the 1 or 2 arg closure applied on each entry of the map
* @return returns the self parameter
* @since 1.5.0
*/
public static <K, V> Map each(Map self, Closure closure) {
for (Map.Entry entry : self.entrySet()) {
callClosureForMapEntry(closure, entry);
}
return self;
}
/**
* Allows a Map to be iterated through in reverse order using a closure.
*
* In general, the order in which the map contents are processed
* cannot be guaranteed. In practise, specialized forms of Map,
* e.g. a TreeMap will have its contents processed according to the
* reverse of the natural ordering of the map.
*
* @param self the map over which we iterate
* @param closure the 1 or 2 arg closure applied on each entry of the map
* @return returns the self parameter
* @see #each(Map, Closure)
* @since 1.7.2
*/
public static <K, V> Map reverseEach(Map self, Closure closure) {
final Iterator<Map.Entry entries = reverse(self.entrySet().iterator());
while (entries.hasNext()) {
callClosureForMapEntry(closure, entries.next());
}
return self;
}
/**
* Allows a Map to be iterated through using a closure. If the
* closure takes two parameters then it will be passed the Map.Entry and
* the item's index (a counter starting at zero) otherwise if the closure
* takes three parameters then it will be passed the key, the value, and
* the index.
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].eachWithIndex { key, value, index -> result += "$index($key$value)" }
* assert result == "0(a1)1(b3)"</pre>
* <pre class="groovyTestCase">def result = ""
* [a:1, b:3].eachWithIndex { entry, index -> result += "$index($entry)" }
* assert result == "0(a=1)1(b=3)"</pre>
*
* @param self the map over which we iterate
* @param closure a 2 or 3 arg Closure to operate on each item
* @return the self Object
* @since 1.5.0
*/
public static <K, V> Map eachWithIndex(Map self, Closure closure) {
int counter = 0;
for (Map.Entry entry : self.entrySet()) {
callClosureForMapEntryAndCounter(closure, entry, counter++);
}
return self;
}
/**
* Iterate over each element of the list in the reverse order.
* <pre class="groovyTestCase">def result = []
* [1,2,3].reverseEach { result << it }
* assert result == [3,2,1]</pre>
*
* @param self a List
* @param closure a closure to which each item is passed.
* @return the original list
* @since 1.5.0
*/
public static <T> List reverseEach(List self, Closure closure) {
each(new ReverseListIterator<T>(self), closure);
return self;
}
/**
* Iterate over each element of the array in the reverse order.
*
* @param self an Object array
* @param closure a closure to which each item is passed
* @return the original array
* @since 1.5.2
*/
public static <T> T[] reverseEach(T[] self, Closure closure) {
each(new ReverseListIterator<T>(Arrays.asList(self)), closure);
return self;
}
/**
* Used to determine if the given predicate closure is valid (i.e.&nsbp;returns
* <code>true for all items in this data structure).
* A simple example for a list:
* <pre>def list = [3,4,5]
* def greaterThanTwo = list.every { it > 2 }
* </pre>
*
* @param self the object over which we iterate
* @param closure the closure predicate used for matching
* @return true if every iteration of the object matches the closure predicate
* @since 1.0
*/
public static boolean every(Object self, Closure closure) {
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
if (!DefaultTypeTransformation.castToBoolean(closure.call(iter.next()))) {
return false;
}
}
return true;
}
/**
* Iterates over the entries of a map, and checks whether a predicate is
* valid for all entries. If the
* closure takes one parameter then it will be passed the Map.Entry
* otherwise if the closure takes two parameters then it will be
* passed the key and the value.
* <pre class="groovyTestCase">def map = [a:1, b:2.0, c:2L]
* assert !map.every { key, value -> value instanceof Integer }
* assert map.every { entry -> entry.value instanceof Number }</pre>
*
* @param self the map over which we iterate
* @param closure the 1 or 2 arg Closure predicate used for matching
* @return true if every entry of the map matches the closure predicate
* @since 1.5.0
*/
public static <K, V> boolean every(Map self, Closure closure) {
for (Map.Entry entry : self.entrySet()) {
if (!DefaultTypeTransformation.castToBoolean(callClosureForMapEntry(closure, entry))) {
return false;
}
}
return true;
}
/**
* Iterates over every element of a collection, and checks whether all
* elements are <code>true according to the Groovy Truth.
* Equivalent to <code>self.every({element -> element})
*
* @param self the object over which we iterate
* @return true if every item in the collection matches the closure
* predicate
* @since 1.5.0
*/
public static boolean every(Object self) {
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
if (!DefaultTypeTransformation.castToBoolean(iter.next())) {
return false;
}
}
return true;
}
/**
* Iterates over the contents of an object or collection, and checks whether a
* predicate is valid for at least one element.
*
* @param self the object over which we iterate
* @param closure the closure predicate used for matching
* @return true if any iteration for the object matches the closure predicate
* @since 1.0
*/
public static boolean any(Object self, Closure closure) {
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
if (DefaultTypeTransformation.castToBoolean(closure.call(iter.next()))) {
return true;
}
}
return false;
}
/**
* Iterates over the entries of a map, and checks whether a predicate is
* valid for at least one entry. If the
* closure takes one parameter then it will be passed the Map.Entry
* otherwise if the closure takes two parameters then it will be
* passed the key and the value.
* <pre class="groovyTestCase">
* assert [2:3, 4:5, 5:10].any { key, value -> key * 2 == value }
* assert ![2:3, 4:5, 5:10].any { entry -> entry.key == entry.value * 2 }
* </pre>
*
* @param self the map over which we iterate
* @param closure the 1 or 2 arg closure predicate used for matching
* @return true if any entry in the map matches the closure predicate
* @since 1.5.0
*/
public static <K, V> boolean any(Map self, Closure> closure) {
for (Map.Entry<K, V> entry : self.entrySet()) {
if (DefaultTypeTransformation.castToBoolean(callClosureForMapEntry(closure, entry))) {
return true;
}
}
return false;
}
/**
* Iterates over the elements of a collection, and checks whether at least
* one element is true according to the Groovy Truth.
* Equivalent to self.any({element -> element})
*
* @param self the object over which we iterate
* @return true if any item in the collection matches the closure predicate
* @since 1.5.0
*/
public static boolean any(Object self) {
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
if (DefaultTypeTransformation.castToBoolean(iter.next())) {
return true;
}
}
return false;
}
/**
* Iterates over the collection of items which this Object represents and returns each item that matches
* the given filter - calling the <code>{@link #isCase(java.lang.Object, java.lang.Object)}
* method used by switch statements. This method can be used with different
* kinds of filters like regular expressions, classes, ranges etc.
* Example:
* <pre class="groovyTestCase">
* def list = ['a', 'b', 'aa', 'bc', 3, 4.5]
* assert list.grep( ~/a+/ ) == ['a', 'aa']
* assert list.grep( ~/../ ) == ['aa', 'bc']
* assert list.grep( Number ) == [ 3, 4.5 ]
* assert list.grep{ it.toString().size() == 1 } == [ 'a', 'b', 3 ]
* </pre>
*
* @param self the object over which we iterate
* @param filter the filter to perform on the object (using the {@link #isCase(java.lang.Object, java.lang.Object)} method)
* @return a collection of objects which match the filter
* @since 1.5.6
*/
public static Collection grep(Object self, Object filter) {
Collection answer = createSimilarOrDefaultCollection(self);
MetaClass metaClass = InvokerHelper.getMetaClass(filter);
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
Object object = iter.next();
if (DefaultTypeTransformation.castToBoolean(metaClass.invokeMethod(filter, "isCase", object))) {
answer.add(object);
}
}
return answer;
}
/**
* Iterates over the collection of items which this Object represents and returns each item that matches
* using the IDENTITY Closure as a filter - effectively returning all elements which satisfy Groovy truth.
* <p/>
* Example:
* <pre class="groovyTestCase">
* def items = [1, 2, 0, false, true, '', 'foo', [], [4, 5], null]
* assert items.grep() == [1, 2, true, 'foo', [4, 5]]
* </pre>
*
* @param self the object over which we iterate
* @return a collection of objects which match the filter
* @since 1.8.1
* @see Closure#IDENTITY
*/
public static Collection grep(Object self) {
return grep(self, Closure.IDENTITY);
}
/**
* Counts the number of occurrences of the given value from the
* items within this Iterator.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
* The iterator will become exhausted of elements after determining the count value.
*
* @param self the Iterator from which we count the number of matching occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.5.0
*/
public static Number count(Iterator self, Object value) {
long answer = 0;
while (self.hasNext()) {
if (DefaultTypeTransformation.compareEqual(self.next(), value)) {
++answer;
}
}
// for b/c with Java return an int if we can
if (answer <= Integer.MAX_VALUE) return (int) answer;
return answer;
}
/**
* Counts the number of occurrences which satisfy the given closure from the
* items within this Iterator.
* The iterator will become exhausted of elements after determining the count value.
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [2,4,2,1,3,5,2,4,3].toSet().iterator().count{ it % 2 == 0 } == 2
*
* @param self the Iterator from which we count the number of matching occurrences
* @param closure a closure condition
* @return the number of occurrences
* @since 1.8.0
*/
public static Number count(Iterator self, Closure closure) {
long answer = 0;
while (self.hasNext()) {
if (DefaultTypeTransformation.castToBoolean(closure.call(self.next()))) {
++answer;
}
}
// for b/c with Java return an int if we can
if (answer <= Integer.MAX_VALUE) return (int) answer;
return answer;
}
/**
* Counts the number of occurrences of the given value inside this collection.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [2,4,2,1,3,5,2,4,3].count(4) == 2
*
* @param self the collection within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.0
*/
public static Number count(Collection self, Object value) {
return count(self.iterator(), value);
}
/**
* Counts the number of occurrences which satisfy the given closure from inside this collection.
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [2,4,2,1,3,5,2,4,3].count{ it % 2 == 0 } == 5
*
* @param self the collection within which we count the number of occurrences
* @param closure a closure condition
* @return the number of occurrences
* @since 1.8.0
*/
public static Number count(Collection self, Closure closure) {
return count(self.iterator(), closure);
}
/**
* Counts the number of occurrences which satisfy the given closure from inside this map.
* If the closure takes one parameter then it will be passed the Map.Entry.
* Otherwise, the closure should take two parameters and will be passed the key and value.
* <p>
* Example usage:
* <pre class="groovyTestCase">assert [a:1, b:1, c:2, d:2].count{ k,v -> k == 'a' || v == 2 } == 3
*
* @param self the map within which we count the number of occurrences
* @param closure a 1 or 2 arg Closure condition applying on the entries
* @return the number of occurrences
* @since 1.8.0
*/
public static Number count(Map self, Closure<?> closure) {
long answer = 0;
for (Object entry : self.entrySet()) {
if (DefaultTypeTransformation.castToBoolean(callClosureForMapEntry(closure, (Map.Entry) entry))) {
++answer;
}
}
// for b/c with Java return an int if we can
if (answer <= Integer.MAX_VALUE) return (int) answer;
return answer;
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(Object[] self, Object value) {
return count(Arrays.asList(self), value);
}
/**
* Counts the number of occurrences which satisfy the given closure from inside this array.
*
* @param self the array within which we count the number of occurrences
* @param closure a closure condition
* @return the number of occurrences
* @since 1.8.0
*/
public static Number count(Object[] self, Closure closure) {
return count(Arrays.asList(self), closure);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(int[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(long[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(short[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(char[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(boolean[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(double[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(float[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Counts the number of occurrences of the given value inside this array.
* Comparison is done using Groovy's == operator (using
* <code>compareTo(value) == 0 or equals(value) ).
*
* @param self the array within which we count the number of occurrences
* @param value the value being searched for
* @return the number of occurrences
* @since 1.6.4
*/
public static Number count(byte[] self, Object value) {
return count(InvokerHelper.asIterator(self), value);
}
/**
* Convert a Collection to a List. Always returns a new List
* even if the Collection is already a List.
* <p>
* Example usage:
* <pre class="groovyTestCase">def x = [1,2,3] as HashSet
* assert x.class == HashSet
* assert x.toList() instanceof List</pre>
*
* @param self a collection
* @return a List
* @since 1.0
*/
public static <T> List toList(Collection self) {
List<T> answer = new ArrayList(self.size());
answer.addAll(self);
return answer;
}
/**
* Convert an iterator to a List. The iterator will become
* exhausted of elements after making this conversion.
*
* @param self an iterator
* @return a List
* @since 1.5.0
*/
public static <T> List toList(Iterator self) {
List<T> answer = new ArrayList();
while (self.hasNext()) {
answer.add(self.next());
}
return answer;
}
/**
* Convert an enumeration to a List.
*
* @param self an enumeration
* @return a List
* @since 1.5.0
*/
public static <T> List toList(Enumeration self) {
List<T> answer = new ArrayList();
while (self.hasMoreElements()) {
answer.add(self.nextElement());
}
return answer;
}
/**
* Iterates through this object transforming each value into a new value using the
* closure as a transformer, returning a list of transformed values.
* Example:
* <pre class="groovyTestCase">def list = [1, 'a', 1.23, true ]
* def types = list.collect { it.class }
* assert types == [Integer, String, BigDecimal, Boolean]</pre>
*
* @param self the values of the object to transform
* @param closure the closure used to transform each element of the collection
* @return a List of the transformed values
* @since 1.0
*/
public static <T> List collect(Object self, Closure closure) {
return (List<T>) collect(self, new ArrayList(), closure);
}
/**
* Iterates through this object transforming each object into a new value using the closure
* as a transformer and adding it to the collection, returning the resulting collection.
*
* @param self the values of the object to transform
* @param collection the Collection to which the transformed values are added
* @param closure the closure used to map each element of the collection
* @return the given collection after the transformed values are added
* @since 1.0
*/
public static <T> Collection collect(Object self, Collection collection, Closure extends T> closure) {
for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
collection.add(closure.call(iter.next()));
}
return collection;
}
/**
* Iterates through this collection transforming each entry into a new value using the closure
* as a transformer, returning a list of transformed values.
* <pre class="groovyTestCase">assert [2,4,6] == [1,2,3].collect { it * 2 }
*
* @param self a collection
* @param closure the closure used for mapping
* @return a List of the transformed values
* @since 1.0
*/
public static <T> List collect(Collection> self, Closure closure) {
return (List<T>) collect(self, new ArrayList(self.size()), closure);
}
/**
* Iterates through this collection transforming each value into a new value using the closure
* as a transformer, returning an initial collection plus the transformed values.
* <pre class="groovyTestCase">assert [1,2,3] as HashSet == [2,4,5,6].collect(new HashSet()) { (int)(it / 2) }
*
* @param self a collection
* @param collection an initial Collection to which the transformed values are added
* @param closure the closure used to transform each element of the collection
* @return the resulting collection of transformed values
* @since 1.0
*/
public static <T> Collection collect(Collection> self, Collection collection, Closure extends T> closure) {
for (Iterator iter = self.iterator(); iter.hasNext();) {
collection.add(closure.call(iter.next()));
if (closure.getDirective() == Closure.DONE) {
break;
}
}
return collection;
}
/**
* Alias for collectNested
*
* @deprecated Use collectNested instead
* @see #collectNested(Collection, Closure)
* @since 1.5.2
*/
public static List collectAll(Collection self, Closure closure) {
return collectNested(self, closure);
}
/**
* Recursively iterates through this collection transforming each non-Collection value
* into a new value using the closure as a transformer. Returns a potentially nested
* list of transformed values.
* <pre class="groovyTestCase">assert [2,[4,6],[8],[]] == [1,[2,3],[4],[]].collectNested { it * 2 }
*
* @param self a collection
* @param closure the closure used to transform each element of the collection
* @return the resultant collection
* @since 1.8.1
*/
public static List collectNested(Collection self, Closure closure) {
return (List) collectNested(self, new ArrayList(self.size()), closure);
}
/**
* Alias for collectNested
*
* @deprecated Use collectNested instead
* @see #collectNested(Collection, Collection, Closure)
* @since 1.5.2
*/
public static Collection collectAll(Collection self, Collection collection, Closure closure) {
return collectNested(self, collection, closure);
}
/**
* Recursively iterates through this collection transforming each non-Collection value
* into a new value using the closure as a transformer. Returns a potentially nested
* collection of transformed values.
* <pre class="groovyTestCase">def x = [1,[2,3],[4],[]].collectNested(new Vector()) { it * 2 }
* assert x == [2,[4,6],[8],[]]
* assert x instanceof Vector</pre>
*
* @param self a collection
* @param collection an initial Collection to which the transformed values are added
* @param closure the closure used to transform each element of the collection
* @return the resultant collection
* @since 1.8.1
*/
public static Collection collectNested(Collection self, Collection collection, Closure closure) {
for (Object item : self) {
if (item instanceof Collection) {
Collection c = (Collection) item;
collection.add(collectNested(c, createSimilarCollection(collection, c.size()), closure));
} else {
collection.add(closure.call(item));
}
if (closure.getDirective() == Closure.DONE) {
break;
}
}
return collection;
}
/**
* Projects each item from a source collection to a collection and concatenates (flattens) the resulting collections into a single one.
*
* <pre class="groovyTestCase">
* def nums = 1..10
* def squaresAndCubesOfEvens = nums.collectMany{ it % 2 ? [] : [it**2, it**3] }
* assert squaresAndCubesOfEvens == [4, 8, 16, 64, 36, 216, 64, 512, 100, 1000]
*
* def animals = ['CAT', 'DOG', 'ELEPHANT'] as Set
* def smallAnimals = animals.collectMany{ it.size() > 3 ? [] : [it.toLowerCase()] }
* assert smallAnimals == ['cat', 'dog'] as Set
* </pre>
*
* @param self a collection
* @param closure a projecting Closure returning a collection of items
* @return the projected collections concatenated (flattened) together
* @see #sum(java.util.Collection, groovy.lang.Closure)
*/
public static <T> Collection collectMany(Collection self, Closure> closure) {
Collection<T> result = createSimilarCollection(self);
for (Object next : self) {
result.addAll(closure.call(next));
}
return result;
}
/**
* Projects each item from a source array to a collection and concatenates (flattens) the resulting collections into a single one.
*
* <pre class="groovyTestCase">
* def nums = [1, 2, 3, 4, 5, 6] as Object[]
* def squaresAndCubesOfEvens = nums.collectMany{ it % 2 ? [] : [it**2, it**3] }
* assert squaresAndCubesOfEvens == [4, 8, 16, 64, 36, 216]
* </pre>
*
* @param self an object array
* @param closure a projecting Closure returning a collection of items
* @return the projected collections concatenated (flattened) together
* @see #sum(Object[], groovy.lang.Closure)
*/
public static <T> Collection collectMany(Object[] self, Closure> closure) {
return collectMany(toList(self), closure);
}
/**
* Projects each item from a source iterator to a collection and concatenates (flattens) the resulting collections into a single one.
*
* <pre class="groovyTestCase">
* def numsIter = [1, 2, 3, 4, 5, 6].iterator()
* def squaresAndCubesOfEvens = numsIter.collectMany{ it % 2 ? [] : [it**2, it**3] }
* assert squaresAndCubesOfEvens == [4, 8, 16, 64, 36, 216]
* </pre>
*
* @param self an iterator
* @param closure a projecting Closure returning a collection of items
* @return the projected collections concatenated (flattened) together
* @see #sum(Iterator, groovy.lang.Closure)
*/
public static <T> Collection collectMany(Iterator