groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sun...@apache.org
Subject [39/47] groovy git commit: Move source files to proper packages
Date Wed, 20 Dec 2017 04:29:47 GMT
http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Closure.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Closure.java b/src/main/groovy/groovy/lang/Closure.java
new file mode 100644
index 0000000..99d2ea9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Closure.java
@@ -0,0 +1,1054 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+import org.apache.groovy.internal.util.UncheckedThrow;
+import org.codehaus.groovy.reflection.ReflectionCache;
+import org.codehaus.groovy.reflection.stdclasses.CachedClosureClass;
+import org.codehaus.groovy.runtime.ComposedClosure;
+import org.codehaus.groovy.runtime.CurriedClosure;
+import org.codehaus.groovy.runtime.InvokerHelper;
+import org.codehaus.groovy.runtime.InvokerInvocationException;
+import org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper;
+import org.codehaus.groovy.runtime.memoize.LRUCache;
+import org.codehaus.groovy.runtime.memoize.Memoize;
+import org.codehaus.groovy.runtime.memoize.UnlimitedConcurrentCache;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.io.Writer;
+
+/**
+ * Represents any closure object in Groovy.
+ * <p>
+ * Groovy allows instances of Closures to be called in a
+ * short form. For example:
+ * <pre class="groovyTestCase">
+ * def a = 1
+ * def c = { a }
+ * assert c() == 1
+ * </pre>
+ * To be able to use a Closure in this way with your own
+ * subclass, you need to provide a doCall method with any
+ * signature you want to. This ensures that
+ * {@link #getMaximumNumberOfParameters()} and
+ * {@link #getParameterTypes()} will work too without any
+ * additional code. If no doCall method is provided a
+ * closure must be used in its long form like
+ * <pre class="groovyTestCase">
+ * def a = 1
+ * def c = {a}
+ * assert c.call() == 1
+ * </pre>
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author <a href="mailto:tug@wilson.co.uk">John Wilson</a>
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
+ * @author Graeme Rocher
+ * @author Paul King
+ */
+public abstract class Closure<V> extends GroovyObjectSupport implements Cloneable, Runnable, GroovyCallable<V>, Serializable {
+
+    /**
+     * With this resolveStrategy set the closure will attempt to resolve property references and methods to the
+     * owner first, then the delegate (<b>this is the default strategy</b>).
+     *
+     * For example the following code:
+     * <pre>
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20 ]
+     *         def cl = { y = x + y }
+     *         cl.delegate = data
+     *         cl()
+     *         assert x == 30
+     *         assert y == 70
+     *         assert data == [x:10, y:20]
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     * Will succeed, because the x and y fields declared in the Test class shadow the variables in the delegate.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int OWNER_FIRST = 0;
+
+    /**
+     * With this resolveStrategy set the closure will attempt to resolve property references and methods to the
+     * delegate first then the owner.
+     *
+     * For example the following code:
+     * <pre class="groovyTestCase">
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20 ]
+     *         def cl = { y = x + y }
+     *         cl.delegate = data
+     *         cl.resolveStrategy = Closure.DELEGATE_FIRST
+     *         cl()
+     *         assert x == 30
+     *         assert y == 40
+     *         assert data == [x:10, y:30]
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     * This will succeed, because the x and y variables declared in the delegate shadow the fields in the owner class.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int DELEGATE_FIRST = 1;
+
+    /**
+     * With this resolveStrategy set the closure will resolve property references and methods to the owner only
+     * and not call the delegate at all. For example the following code :
+     *
+     * <pre>
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20, z: 30 ]
+     *         def cl = { y = x + y + z }
+     *         cl.delegate = data
+     *         cl.resolveStrategy = Closure.OWNER_ONLY
+     *         cl()
+     *         println x
+     *         println y
+     *         println data
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     *
+     * will throw "No such property: z" error because even if the z variable is declared in the delegate, no
+     * lookup is made.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int OWNER_ONLY = 2;
+
+    /**
+     * With this resolveStrategy set the closure will resolve property references and methods to the delegate
+     * only and entirely bypass the owner. For example the following code :
+     *
+     * <pre>
+     * class Test {
+     *     def x = 30
+     *     def y = 40
+     *     def z = 50
+     *
+     *     def run() {
+     *         def data = [ x: 10, y: 20 ]
+     *         def cl = { y = x + y + z }
+     *         cl.delegate = data
+     *         cl.resolveStrategy = Closure.DELEGATE_ONLY
+     *         cl()
+     *         println x
+     *         println y
+     *         println data
+     *     }
+     * }
+     *
+     * new Test().run()
+     * </pre>
+     *
+     * will throw an error because even if the owner declares a "z" field, the resolution strategy will bypass
+     * lookup in the owner.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int DELEGATE_ONLY = 3;
+
+    /**
+     * With this resolveStrategy set the closure will resolve property references to itself and go
+     * through the usual MetaClass look-up process. This means that properties and methods are neither resolved
+     * from the owner nor the delegate, but only on the closure object itself. This allows the developer to
+     * override getProperty using ExpandoMetaClass of the closure itself.<p>
+     * <i>Note that local variables are always looked up first, independently of the resolution strategy.</i>
+     */
+    public static final int TO_SELF = 4;
+
+    public static final int DONE = 1, SKIP = 2;
+    private static final Object[] EMPTY_OBJECT_ARRAY = {};
+    public static final Closure IDENTITY = new Closure<Object>(null) {
+        public Object doCall(Object args) {
+            return args;
+        }
+    };
+
+    private Object delegate;
+    private Object owner;
+    private Object thisObject;
+    private int resolveStrategy = OWNER_FIRST;
+    private int directive;
+    protected Class[] parameterTypes;
+    protected int maximumNumberOfParameters;
+    private static final long serialVersionUID = 4368710879820278874L;
+    private BooleanClosureWrapper bcw;
+
+    public Closure(Object owner, Object thisObject) {
+        this.owner = owner;
+        this.delegate = owner;
+        this.thisObject = thisObject;
+
+        final CachedClosureClass cachedClass = (CachedClosureClass) ReflectionCache.getCachedClass(getClass());
+        parameterTypes = cachedClass.getParameterTypes();
+        maximumNumberOfParameters = cachedClass.getMaximumNumberOfParameters();
+    }
+
+    /**
+     * Constructor used when the "this" object for the Closure is null.
+     * This is rarely the case in normal Groovy usage.
+     *
+     * @param owner the Closure owner
+     */
+    public Closure(Object owner) {
+        this(owner, null);
+    }
+
+    /**
+     * Sets the strategy which the closure uses to resolve property references and methods.
+     * The default is Closure.OWNER_FIRST
+     *
+     * @param resolveStrategy The resolve strategy to set
+     *
+     * @see groovy.lang.Closure#DELEGATE_FIRST
+     * @see groovy.lang.Closure#DELEGATE_ONLY
+     * @see groovy.lang.Closure#OWNER_FIRST
+     * @see groovy.lang.Closure#OWNER_ONLY
+     * @see groovy.lang.Closure#TO_SELF
+     */
+    public void setResolveStrategy(int resolveStrategy) {
+        this.resolveStrategy = resolveStrategy;
+    }
+
+    /**
+     * Gets the strategy which the closure uses to resolve methods and properties
+     *
+     * @return The resolve strategy
+     *
+     * @see groovy.lang.Closure#DELEGATE_FIRST
+     * @see groovy.lang.Closure#DELEGATE_ONLY
+     * @see groovy.lang.Closure#OWNER_FIRST
+     * @see groovy.lang.Closure#OWNER_ONLY
+     * @see groovy.lang.Closure#TO_SELF
+     */
+    public int getResolveStrategy() {
+        return resolveStrategy;
+    }
+
+    public Object getThisObject(){
+        return thisObject;
+    }
+
+    public Object getProperty(final String property) {
+        if ("delegate".equals(property)) {
+            return getDelegate();
+        } else if ("owner".equals(property)) {
+            return getOwner();
+        } else if ("maximumNumberOfParameters".equals(property)) {
+            return getMaximumNumberOfParameters();
+        } else if ("parameterTypes".equals(property)) {
+            return getParameterTypes();
+        } else if ("metaClass".equals(property)) {
+            return getMetaClass();
+        } else if ("class".equals(property)) {
+            return getClass();
+        } else if ("directive".equals(property)) {
+            return getDirective();
+        } else if ("resolveStrategy".equals(property)) {
+            return getResolveStrategy();
+        } else if ("thisObject".equals(property)) {
+            return getThisObject();
+        } else {
+            switch(resolveStrategy) {
+                case DELEGATE_FIRST:
+                    return getPropertyDelegateFirst(property);
+                case DELEGATE_ONLY:
+                    return InvokerHelper.getProperty(this.delegate, property);
+                case OWNER_ONLY:
+                    return InvokerHelper.getProperty(this.owner, property);
+                case TO_SELF:
+                    return super.getProperty(property);
+                default:
+                    return getPropertyOwnerFirst(property);
+            }
+        }
+    }
+
+    private Object getPropertyDelegateFirst(String property) {
+        if (delegate == null) return getPropertyOwnerFirst(property);
+        return getPropertyTryThese(property, this.delegate, this.owner);
+    }
+
+    private Object getPropertyOwnerFirst(String property) {
+        return getPropertyTryThese(property, this.owner, this.delegate);
+    }
+
+    private Object getPropertyTryThese(String property, Object firstTry, Object secondTry) {
+        try {
+            // let's try getting the property on the first object
+            return InvokerHelper.getProperty(firstTry, property);
+
+        } catch (MissingPropertyException e1) {
+            if (secondTry != null && firstTry != this && firstTry != secondTry) {
+                try {
+                    // let's try getting the property on the second object
+                    return InvokerHelper.getProperty(secondTry, property);
+                } catch (GroovyRuntimeException e2) {
+                    // ignore, we'll throw e1
+                }
+            }
+            throw e1;
+
+        } catch (MissingFieldException e2)  { // see GROOVY-5875
+            if (secondTry != null && firstTry != this && firstTry != secondTry) {
+                try {
+                    // let's try getting the property on the second object
+                    return InvokerHelper.getProperty(secondTry, property);
+                } catch (GroovyRuntimeException e3) {
+                    // ignore, we'll throw e2
+                }
+            }
+            throw e2;
+        }
+    }
+
+    public void setProperty(String property, Object newValue) {
+        if ("delegate".equals(property)) {
+            setDelegate(newValue);
+        } else if ("metaClass".equals(property)) {
+            setMetaClass((MetaClass) newValue);
+        } else if ("resolveStrategy".equals(property)) {
+            setResolveStrategy(((Number) newValue).intValue());
+        } else if ("directive".equals(property)) {
+            setDirective(((Number) newValue).intValue());
+        } else {
+            switch(resolveStrategy) {
+                case DELEGATE_FIRST:
+                    setPropertyDelegateFirst(property, newValue);
+                break;
+                case DELEGATE_ONLY:
+                    InvokerHelper.setProperty(this.delegate, property, newValue);
+                break;
+                case OWNER_ONLY:
+                    InvokerHelper.setProperty(this.owner, property, newValue);
+                break;
+                case TO_SELF:
+                    super.setProperty(property, newValue);
+                break;
+                default:
+                    setPropertyOwnerFirst(property, newValue);
+            }
+        }
+    }
+
+    private void setPropertyDelegateFirst(String property, Object newValue) {
+        if (delegate == null) setPropertyOwnerFirst(property, newValue);
+        else setPropertyTryThese(property, newValue, this.delegate, this.owner);
+    }
+
+    private void setPropertyOwnerFirst(String property, Object newValue) {
+        setPropertyTryThese(property, newValue, this.owner, this.delegate);
+    }
+
+    private void setPropertyTryThese(String property, Object newValue, Object firstTry, Object secondTry) {
+        try {
+            // let's try setting the property on the first object
+            InvokerHelper.setProperty(firstTry, property, newValue);
+        } catch (GroovyRuntimeException e1) {
+            if (firstTry != null && firstTry != this && firstTry != secondTry) {
+                try {
+                    // let's try setting the property on the second object
+                    InvokerHelper.setProperty(secondTry, property, newValue);
+                    return;
+                } catch (GroovyRuntimeException e2) {
+                    // ignore, we'll throw e1
+                }
+            }
+            throw e1;
+        }
+    }
+
+    public boolean isCase(Object candidate){
+        if (bcw==null) {
+            bcw = new BooleanClosureWrapper(this);
+        }
+        return bcw.call(candidate);
+    }
+
+    /**
+     * Invokes the closure without any parameters, returning any value if applicable.
+     *
+     * @return the value if applicable or null if there is no return statement in the closure
+     */
+    public V call() {
+        final Object[] NOARGS = EMPTY_OBJECT_ARRAY;
+        return call(NOARGS);
+    }
+
+    @SuppressWarnings("unchecked")
+    public V call(Object... args) {
+        try {
+            return (V) getMetaClass().invokeMethod(this,"doCall",args);
+        } catch (InvokerInvocationException e) {
+            UncheckedThrow.rethrow(e.getCause());
+            return null; // unreachable statement
+        }  catch (Exception e) {
+            return (V) throwRuntimeException(e);
+        }
+    }
+
+    /**
+     * Invokes the closure, returning any value if applicable.
+     *
+     * @param arguments could be a single value or a List of values
+     * @return the value if applicable or null if there is no return statement in the closure
+     */
+    public V call(final Object arguments) {
+        return call(new Object[]{arguments});
+    }
+
+    protected static Object throwRuntimeException(Throwable throwable) {
+        if (throwable instanceof RuntimeException) {
+            throw (RuntimeException) throwable;
+        } else {
+            throw new GroovyRuntimeException(throwable.getMessage(), throwable);
+        }
+    }
+
+    /**
+     * @return the owner Object to which method calls will go which is
+     *         typically the outer class when the closure is constructed
+     */
+    public Object getOwner() {
+        return this.owner;
+    }
+
+    /**
+     * @return the delegate Object to which method calls will go which is
+     *         typically the outer class when the closure is constructed
+     */
+    public Object getDelegate() {
+        return this.delegate;
+    }
+
+    /**
+     * Allows the delegate to be changed such as when performing markup building
+     *
+     * @param delegate the new delegate
+     */
+    public void setDelegate(Object delegate) {
+        this.delegate = delegate;
+    }
+
+    /**
+     * @return the parameter types of the longest doCall method
+     * of this closure
+     */
+    public Class[] getParameterTypes() {
+        return parameterTypes;
+    }
+
+    /**
+     * @return the maximum number of parameters a doCall method
+     * of this closure can take
+     */
+    public int getMaximumNumberOfParameters() {
+        return maximumNumberOfParameters;
+    }
+
+    /**
+     * @return a version of this closure which implements Writable.  Note that
+     * the returned Writable also overrides {@link #toString()} in order
+     * to allow rendering the result directly to a String.
+     */
+    public Closure asWritable() {
+        return new WritableClosure();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Runnable#run()
+     */
+    public void run() {
+        call();
+    }
+
+    /**
+     * Support for Closure currying.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def multiply = { a, b -> a * b }
+     * def doubler = multiply.curry(2)
+     * assert doubler(4) == 8
+     * </pre>
+     * Note: special treatment is given to Closure vararg-style capability.
+     * If you curry a vararg parameter, you don't consume the entire vararg array
+     * but instead the first parameter of the vararg array as the following example shows:
+     * <pre class="groovyTestCase">
+     * def a = { one, two, Object[] others -> one + two + others.sum() }
+     * assert a.parameterTypes.name == ['java.lang.Object', 'java.lang.Object', '[Ljava.lang.Object;']
+     * assert a(1,2,3,4) == 10
+     * def b = a.curry(1)
+     * assert b.parameterTypes.name == ['java.lang.Object', '[Ljava.lang.Object;']
+     * assert b(2,3,4) == 10
+     * def c = b.curry(2)
+     * assert c.parameterTypes.name == ['[Ljava.lang.Object;']
+     * assert c(3,4) == 10
+     * def d = c.curry(3)
+     * assert d.parameterTypes.name == ['[Ljava.lang.Object;']
+     * assert d(4) == 10
+     * def e = d.curry(4)
+     * assert e.parameterTypes.name == ['[Ljava.lang.Object;']
+     * assert e() == 10
+     * assert e(5) == 15
+     * </pre>
+     *
+     *
+     * @param arguments the arguments to bind
+     * @return the new closure with its arguments bound
+     */
+    public Closure<V> curry(final Object... arguments) {
+        return new CurriedClosure<V>(this, arguments);
+    }
+
+    /**
+     * Support for Closure currying.
+     *
+     * @param argument the argument to bind
+     * @return the new closure with the argument bound
+     * @see #curry(Object...)
+     */
+    public Closure<V> curry(final Object argument) {
+        return curry(new Object[]{argument});
+    }
+
+    /**
+     * Support for Closure "right" currying.
+     * Parameters are supplied on the right rather than left as per the normal curry() method.
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def divide = { a, b -> a / b }
+     * def halver = divide.rcurry(2)
+     * assert halver(8) == 4
+     * </pre>
+     *
+     * The position of the curried parameters will be calculated lazily, for example,
+     * if two overloaded doCall methods are available, the supplied arguments plus the
+     * curried arguments will be concatenated and the result used for method selection.
+     *
+     * @param arguments the arguments to bind
+     * @return the new closure with its arguments bound
+     * @see #curry(Object...)
+     */
+    public Closure<V> rcurry(final Object... arguments) {
+        return new CurriedClosure<V>(-arguments.length, this, arguments);
+    }
+
+    /**
+     * Support for Closure "right" currying.
+     *
+     * @param argument the argument to bind
+     * @return the new closure with the argument bound
+     * @see #rcurry(Object...)
+     */
+    public Closure<V> rcurry(final Object argument) {
+        return rcurry(new Object[]{argument});
+    }
+
+    /**
+     * Support for Closure currying at a given index.
+     * Parameters are supplied from index position "n".
+     * Typical usage:
+     * <pre>
+     * def caseInsensitive = { a, b -> a.toLowerCase() <=> b.toLowerCase() } as Comparator
+     * def caseSensitive = { a, b -> a <=> b } as Comparator
+     * def animals1 = ['ant', 'dog', 'BEE']
+     * def animals2 = animals1 + ['Cat']
+     * // curry middle param of this utility method:
+     * // Collections#binarySearch(List list, Object key, Comparator c)
+     * def catSearcher = Collections.&binarySearch.ncurry(1, "cat")
+     * [[animals1, animals2], [caseInsensitive, caseSensitive]].combinations().each{ a, c ->
+     *   def idx = catSearcher(a.sort(c), c)
+     *   print a.sort(c).toString().padRight(22)
+     *   if (idx < 0) println "Not found but would belong in position ${-idx - 1}"
+     *   else println "Found at index $idx"
+     * }
+     * // =>
+     * // [ant, BEE, dog]       Not found but would belong in position 2
+     * // [ant, BEE, Cat, dog]  Found at index 2
+     * // [BEE, ant, dog]       Not found but would belong in position 2
+     * // [BEE, Cat, ant, dog]  Not found but would belong in position 3
+     * </pre>
+     *
+     * The position of the curried parameters will be calculated eagerly
+     * and implies all arguments prior to the specified n index are supplied.
+     * Default parameter values prior to the n index will not be available.
+     *
+     * @param n the index from which to bind parameters (may be -ve in which case it will be normalized)
+     * @param arguments the arguments to bind
+     * @return the new closure with its arguments bound
+     * @see #curry(Object...)
+     */
+    public Closure<V> ncurry(int n, final Object... arguments) {
+        return new CurriedClosure<V>(n, this, arguments);
+    }
+
+    /**
+     * Support for Closure currying at a given index.
+     *
+     * @param argument the argument to bind
+     * @return the new closure with the argument bound
+     * @see #ncurry(int, Object...)
+     */
+    public Closure<V> ncurry(int n, final Object argument) {
+        return ncurry(n, new Object[]{argument});
+    }
+
+    /**
+     * Support for Closure forward composition.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def times2 = { a -> a * 2 }
+     * def add3 = { a -> a + 3 }
+     * def timesThenAdd = times2 >> add3
+     * // equivalent: timesThenAdd = { a -> add3(times2(a)) }
+     * assert timesThenAdd(3) == 9
+     * </pre>
+     *
+     * @param other the Closure to compose with the current Closure
+     * @return the new composed Closure
+     */
+    public <W> Closure<W> rightShift(final Closure<W> other) {
+        return new ComposedClosure<W>(this, other);
+    }
+
+    /**
+     * Support for Closure reverse composition.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def times2 = { a -> a * 2 }
+     * def add3 = { a -> a + 3 }
+     * def addThenTimes = times2 << add3
+     * // equivalent: addThenTimes = { a -> times2(add3(a)) }
+     * assert addThenTimes(3) == 12
+     * </pre>
+     *
+     * @param other the Closure to compose with the current Closure
+     * @return the new composed Closure
+     */
+    public Closure<V> leftShift(final Closure other) {
+        return new ComposedClosure<V>(other, this);
+    }
+
+    /* *
+     * Alias for calling a Closure for non-closure arguments.
+     * <p>
+     * Typical usage:
+     * <pre class="groovyTestCase">
+     * def times2 = { a -> a * 2 }
+     * def add3 = { a -> a * 3 }
+     * assert add3 << times2 << 3 == 9
+     * </pre>
+     *
+     * @param arg the argument to call the closure with
+     * @return the result of calling the Closure
+     */
+    public V leftShift(final Object arg) {
+        return call(arg);
+    }
+
+    /**
+     * Creates a caching variant of the closure.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant will keep all cached values forever, i.e. till the closure gets garbage-collected.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     *
+     * @return A new closure forwarding to the original one while caching the results
+     */
+    public Closure<V> memoize() {
+        return Memoize.buildMemoizeFunction(new UnlimitedConcurrentCache(), this);
+    }
+
+    /**
+     * Creates a caching variant of the closure with upper limit on the cache size.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant will keep all values until the upper size limit is reached. Then the values in the cache start rotating
+     * using the LRU (Last Recently Used) strategy.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     *
+     * @param maxCacheSize The maximum size the cache can grow to
+     * @return A new function forwarding to the original one while caching the results
+     */
+    public Closure<V> memoizeAtMost(final int maxCacheSize) {
+        if (maxCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the maxCacheSize parameter for memoizeAtMost.");
+
+        return Memoize.buildMemoizeFunction(new LRUCache(maxCacheSize), this);
+    }
+
+    /**
+     * Creates a caching variant of the closure with automatic cache size adjustment and lower limit
+     * on the cache size.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant allows the garbage collector to release entries from the cache and at the same time allows
+     * the user to specify how many entries should be protected from the eventual gc-initiated eviction.
+     * Cached entries exceeding the specified preservation threshold are made available for eviction based on
+     * the LRU (Last Recently Used) strategy.
+     * Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the limits
+     * set by the user if memory is plentiful.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter
+     * might not be respected accurately in such scenarios for some periods of time. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     * @param protectedCacheSize Number of cached return values to protect from garbage collection
+     * @return A new function forwarding to the original one while caching the results
+     */
+    public Closure<V> memoizeAtLeast(final int protectedCacheSize) {
+        if (protectedCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the protectedCacheSize parameter for memoizeAtLeast.");
+
+        return Memoize.buildSoftReferenceMemoizeFunction(protectedCacheSize, new UnlimitedConcurrentCache(), this);
+    }
+
+    /**
+     * Creates a caching variant of the closure with automatic cache size adjustment and lower and upper limits
+     * on the cache size.
+     * Whenever the closure is called, the mapping between the parameters and the return value is preserved in cache
+     * making subsequent calls with the same arguments fast.
+     * This variant allows the garbage collector to release entries from the cache and at the same time allows
+     * the user to specify how many entries should be protected from the eventual gc-initiated eviction.
+     * Cached entries exceeding the specified preservation threshold are made available for eviction based on
+     * the LRU (Last Recently Used) strategy.
+     * Given the non-deterministic nature of garbage collector, the actual cache size may grow well beyond the protected
+     * size limits set by the user, if memory is plentiful.
+     * Also, this variant will never exceed in size the upper size limit. Once the upper size limit has been reached,
+     * the values in the cache start rotating using the LRU (Last Recently Used) strategy.
+     * The returned function can be safely used concurrently from multiple threads, however, the implementation
+     * values high average-scenario performance and so concurrent calls on the memoized function with identical argument values
+     * may not necessarily be able to benefit from each other's cached return value. Also the protectedCacheSize parameter
+     * might not be respected accurately in such scenarios for some periods of time. With this having been mentioned,
+     * the performance trade-off still makes concurrent use of memoized functions safe and highly recommended.
+     *
+     * The cache gets garbage-collected together with the memoized closure.
+     * @param protectedCacheSize Number of cached return values to protect from garbage collection
+     * @param maxCacheSize The maximum size the cache can grow to
+     * @return A new function forwarding to the original one while caching the results
+     */
+    public Closure<V> memoizeBetween(final int protectedCacheSize, final int maxCacheSize) {
+        if (protectedCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the protectedCacheSize parameter for memoizeBetween.");
+        if (maxCacheSize < 0) throw new IllegalArgumentException("A non-negative number is required as the maxCacheSize parameter for memoizeBetween.");
+        if (protectedCacheSize > maxCacheSize) throw new IllegalArgumentException("The maxCacheSize parameter to memoizeBetween is required to be greater or equal to the protectedCacheSize parameter.");
+
+        return Memoize.buildSoftReferenceMemoizeFunction(protectedCacheSize, new LRUCache(maxCacheSize), this);
+    }
+
+    /**
+     * Builds a trampolined variant of the current closure.
+     * To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism
+     * and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of
+     * the calculation and, instead of a recursive call to itself or another function, it return back a new closure,
+     * which will be executed by the trampoline as the next step.
+     * Once a non-closure value is returned, the trampoline stops and returns the value as the final result.
+     * Here is an example:
+     * <pre>
+     * def fact
+     * fact = { n, total ->
+     *     n == 0 ? total : fact.trampoline(n - 1, n * total)
+     * }.trampoline()
+     * def factorial = { n -> fact(n, 1G)}
+     * println factorial(20) // => 2432902008176640000
+     * </pre>
+     *
+     * @param args Parameters to the closure, so as the trampoline mechanism can call it
+     * @return A closure, which will execute the original closure on a trampoline.
+     */
+    public Closure<V> trampoline(final Object... args) {
+        return new TrampolineClosure<V>(this.curry(args));
+    }
+
+    /**
+     * Builds a trampolined variant of the current closure.
+     * To prevent stack overflow due to deep recursion, functions can instead leverage the trampoline mechanism
+     * and avoid recursive calls altogether. Under trampoline, the function is supposed to perform one step of
+     * the calculation and, instead of a recursive call to itself or another function, it return back a new closure,
+     * which will be executed by the trampoline as the next step.
+     * Once a non-closure value is returned, the trampoline stops and returns the value as the final result.
+     * @return A closure, which will execute the original closure on a trampoline.
+     * @see #trampoline(Object...)
+     */
+    public Closure<V> trampoline() {
+        return new TrampolineClosure<V>(this);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (final CloneNotSupportedException e) {
+            return null;
+        }
+    }
+
+    /*
+     * Implementation note:
+     *   This has to be an inner class!
+     *
+     * Reason:
+     *   Closure.this.call will call the outer call method, but
+     * with the inner class as executing object. This means any
+     * invokeMethod or getProperty call will be called on this
+     * inner class instead of the outer!
+     */
+    private class WritableClosure extends Closure implements Writable {
+        public WritableClosure() {
+            super(Closure.this);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Writable#writeTo(java.io.Writer)
+         */
+        public Writer writeTo(Writer out) throws IOException {
+            Closure.this.call(new Object[]{out});
+
+            return out;
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.GroovyObject#invokeMethod(java.lang.String, java.lang.Object)
+         */
+        public Object invokeMethod(String method, Object arguments) {
+            if ("clone".equals(method)) {
+                return clone();
+            } else if ("curry".equals(method)) {
+                return curry((Object[]) arguments);
+            } else if ("asWritable".equals(method)) {
+                return asWritable();
+            } else {
+                return Closure.this.invokeMethod(method, arguments);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.GroovyObject#getProperty(java.lang.String)
+         */
+        public Object getProperty(String property) {
+            return Closure.this.getProperty(property);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.GroovyObject#setProperty(java.lang.String, java.lang.Object)
+         */
+        public void setProperty(String property, Object newValue) {
+            Closure.this.setProperty(property, newValue);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#call()
+         */
+        public Object call() {
+            return ((Closure) getOwner()).call();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#call(java.lang.Object)
+         */
+        public Object call(Object arguments) {
+            return ((Closure) getOwner()).call(arguments);
+        }
+
+        public Object call(Object... args) {
+            return ((Closure) getOwner()).call(args);
+        }
+
+        public Object doCall(Object... args) {
+            return call(args);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#getDelegate()
+         */
+        public Object getDelegate() {
+            return Closure.this.getDelegate();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#setDelegate(java.lang.Object)
+         */
+        public void setDelegate(Object delegate) {
+            Closure.this.setDelegate(delegate);
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#getParameterTypes()
+         */
+        public Class[] getParameterTypes() {
+            return Closure.this.getParameterTypes();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#getParameterTypes()
+         */
+        public int getMaximumNumberOfParameters() {
+            return Closure.this.getMaximumNumberOfParameters();
+        }
+
+        /* (non-Javadoc)
+         * @see groovy.lang.Closure#asWritable()
+         */
+        public Closure asWritable() {
+            return this;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Runnable#run()
+         */
+        public void run() {
+            Closure.this.run();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#clone()
+         */
+        public Object clone() {
+            return ((Closure) Closure.this.clone()).asWritable();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        public int hashCode() {
+            return Closure.this.hashCode();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        public boolean equals(Object arg0) {
+            return Closure.this.equals(arg0);
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#toString()
+         */
+        public String toString() {
+            final StringWriter writer = new StringWriter();
+
+            try {
+                writeTo(writer);
+            } catch (IOException e) {
+                return null;
+            }
+
+            return writer.toString();
+        }
+
+        public Closure curry(final Object... arguments) {
+            return (new CurriedClosure(this, arguments)).asWritable();
+        }
+
+        public void setResolveStrategy(int resolveStrategy) {
+            Closure.this.setResolveStrategy(resolveStrategy);
+        }
+
+        public int getResolveStrategy() {
+            return Closure.this.getResolveStrategy();
+        }
+    }
+
+    /**
+     * @return Returns the directive.
+     */
+    public int getDirective() {
+        return directive;
+    }
+
+    /**
+     * @param directive The directive to set.
+     */
+    public void setDirective(int directive) {
+        this.directive = directive;
+    }
+
+    /**
+     * Returns a copy of this closure where the "owner", "delegate" and "thisObject"
+     * fields are null, allowing proper serialization when one of them is not serializable.
+     *
+     * @return a serializable closure.
+     *
+     * @since 1.8.5
+     */
+    @SuppressWarnings("unchecked")
+    public Closure<V> dehydrate() {
+        Closure<V> result = (Closure<V>) this.clone();
+        result.delegate = null;
+        result.owner = null;
+        result.thisObject = null;
+        return result;
+    }
+
+    /**
+     * Returns a copy of this closure for which the delegate, owner and thisObject are
+     * replaced with the supplied parameters. Use this when you want to rehydrate a
+     * closure which has been made serializable thanks to the {@link #dehydrate()}
+     * method.
+     * @param delegate the closure delegate
+     * @param owner the closure owner
+     * @param thisObject the closure "this" object
+     * @return a copy of this closure where owner, delegate and thisObject are replaced
+     *
+     * @since 1.8.5
+     */
+    @SuppressWarnings("unchecked")
+    public Closure<V> rehydrate(Object delegate, Object owner, Object thisObject) {
+        Closure<V> result = (Closure<V>) this.clone();
+        result.delegate = delegate;
+        result.owner = owner;
+        result.thisObject = thisObject;
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ClosureException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ClosureException.java b/src/main/groovy/groovy/lang/ClosureException.java
new file mode 100644
index 0000000..12986ad
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ClosureException.java
@@ -0,0 +1,38 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+/**
+ * An exception thrown by a closure invocation
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ClosureException extends RuntimeException {
+
+    private final Closure closure;
+    
+    public ClosureException(Closure closure, Throwable cause) {
+        super("Exception thrown by call to closure: " + closure + " reason: " + cause, cause);
+        this.closure = closure;
+    }
+
+    public Closure getClosure() {
+        return closure;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/ClosureInvokingMethod.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/ClosureInvokingMethod.java b/src/main/groovy/groovy/lang/ClosureInvokingMethod.java
new file mode 100644
index 0000000..3e54278
--- /dev/null
+++ b/src/main/groovy/groovy/lang/ClosureInvokingMethod.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+/**
+ * An interface for MetaMethods that invoke closures to implements. Used by ExpandoMetaClass
+ *
+ * @see groovy.lang.ExpandoMetaClass
+ * 
+ * @author Graeme Rocher
+ * @since 1.5
+ */
+public interface ClosureInvokingMethod {
+
+    /**
+     * Returns the original closure that this method invokes
+     * @return The closure
+     */
+    Closure getClosure();
+
+    /**
+     * Is it a static method?
+     * @return True if it is
+     */
+    boolean isStatic();
+
+    /**
+     * The method name
+     * @return The method name
+     */
+    String getName();
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/Delegate.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/Delegate.java b/src/main/groovy/groovy/lang/Delegate.java
new file mode 100644
index 0000000..180dc84
--- /dev/null
+++ b/src/main/groovy/groovy/lang/Delegate.java
@@ -0,0 +1,218 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+import groovy.transform.Undefined;
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to automatically delegate part of the functionality of an owner class to the
+ * annotated delegation target. The target can be a field (or property) or a method's return value.
+ * <p>
+ * The delegate type is either the type of the annotated field (or property) or the return type of
+ * the annotated method. The method can be thought of as a getter or factory method for the delegate.
+ * All public instance methods present in the delegate type and not present in the owner class
+ * will be added to owner class at compile time. The implementation of such automatically added
+ * methods is code which calls through to the delegate as per the normal delegate pattern.
+ * <p>
+ * As an example, consider this code:
+ * <pre class="groovyTestCase">
+ * class Event {
+ *     {@code @Delegate} Date when
+ *     String title, url
+ * }
+ *
+ * def gr8conf = new Event(title: "GR8 Conference",
+ *                           url: "http://www.gr8conf.org",
+ *                          when: Date.parse("yyyy/MM/dd", "2009/05/18"))
+ *
+ * def javaOne = new Event(title: "JavaOne",
+ *                           url: "http://java.sun.com/javaone/",
+ *                          when: Date.parse("yyyy/MM/dd", "2009/06/02"))
+ *
+ * assert gr8conf.before(javaOne.when)
+ * </pre>
+ *
+ * In this example, the {@code Event} class will have a method called
+ * {@code before(Date otherDate)} as well as other public methods of the
+ * {@code Date} class.
+ * The implementation of the {@code before()} method will look like this:
+ * <pre>
+ *     public boolean before(Date otherDate) {
+ *         return when.before(otherDate);
+ *     }
+ * </pre>
+ *
+ * By default, the owner class will also be modified to implement any interfaces
+ * implemented by the delegate type. So, in the example above, because {@code Date}
+ * implements {@code Cloneable} the following will be true:
+ *
+ * <pre>
+ * assert gr8conf instanceof Cloneable
+ * </pre>
+ *
+ * This behavior can be disabled by setting the
+ * annotation's {@code interfaces} element to false,
+ * i.e. {@code @Delegate(interfaces = false)}, e.g. in the above
+ * example, the delegate definition would become:
+ * <pre>
+ *     {@code @Delegate}(interfaces = false) Date when
+ * </pre>
+ * and the following would be true:
+ * <pre>
+ * assert !(gr8conf instanceof Cloneable)
+ * </pre>
+ *
+ * If multiple delegation targets are used and the same method signature occurs
+ * in more than one of the respective delegate types, then the delegate will be
+ * made to the first defined target having that signature. If this does occur,
+ * it might be regarded as a smell (or at least poor style) and it might be
+ * clearer to do the delegation by long hand.
+ * <p>
+ * By default, methods of the delegate type marked as {@code @Deprecated} are
+ * not automatically added to the owner class (but see the technical note
+ * about interfaces below). You can force these methods to
+ * be added by setting the annotation's {@code deprecated} element to true,
+ * i.e. {@code @Delegate(deprecated = true)}.
+ * <p>
+ * For example, in the example above if we change the delegate definition to:
+ * <pre>
+ *     {@code @Delegate}(deprecated = true) Date when
+ * </pre>
+ * then the following additional lines will execute successfully (during 2009):
+ * <pre>
+ * assert gr8conf.year + 1900 == 2009
+ * assert gr8conf.toGMTString().contains(" 2009 ")
+ * </pre>
+ * Otherwise these lines produce a groovy.lang.MissingPropertyException
+ * or groovy.lang.MissingMethodException respectively as those two methods are
+ * {@code @Deprecated} in {@code Date}.
+ * <p>
+ * <b>Technical notes</b>:
+ * <ul>
+ * <li>Static methods, synthetic methods or methods from the <code>GroovyObject</code> interface
+ * are not candidates for delegation</li>
+ * <li>Non-abstract non-static methods defined in the owner class or its superclasses take
+ * precedence over methods with identical signatures from a {@code @Delegate} target</li>
+ * <li>All methods defined in the owner class (including static, abstract or private etc.)
+ * take precedence over methods with identical signatures from a {@code @Delegate} target</li>
+ * <li>Recursive delegation to your own class is not allowed</li>
+ * <li>Mixing of {@code @Delegate} with default method arguments is known not to work in some cases.
+ * We recommend not using these features together.</li>
+ * <li>When the delegate type is an interface, the {@code deprecated} attribute will be
+ * ignored if the owner class implements that interface (i.e. you must set {@code interfaces=false}
+ * if you want the {@code deprecated} attribute to be used). Otherwise, the resulting class would
+ * not compile anyway without manually adding in any deprecated methods in the interface.</li>
+ * <li>{@code @Delegate} can work in combination with {@code @Lazy} when annotating a field (or property)</li>
+ * </ul>
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.DelegateASTTransformation")
+public @interface Delegate {
+    /**
+     * @return true if owner class should implement interfaces implemented by delegate type
+     */
+    boolean interfaces() default true;
+
+    /**
+     * Whether to apply the delegate pattern to deprecated methods; to avoid compilation
+     * errors, this is ignored if the type of the delegate target is an interface and
+     * {@code interfaces=true}.
+     *
+     * @return true if owner class should delegate to methods annotated with @Deprecated
+     */
+    boolean deprecated() default false;
+
+    /**
+     * Whether to carry over annotations from the methods of the delegate
+     * to your delegating method. Currently Closure annotation members are
+     * not supported.
+     *
+     * @return true if generated delegate methods should keep method annotations
+     */
+    boolean methodAnnotations() default false;
+
+    /**
+     * Whether to carry over annotations from the parameters of delegate
+     * methods to your delegating method. Currently Closure annotation members are
+     * not supported.
+     *
+     * @return true if generated delegate methods should keep parameter annotations
+     */
+    boolean parameterAnnotations() default false;
+
+    /**
+     * List of method and/or property names to exclude when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
+     * For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * If interfaces is true (the default), you will need to manually supply any methods excluded
+     * from delegation that are required for the interface.
+     * @since 2.2.0
+     */
+    String[] excludes() default {};
+
+
+    /**
+     * List of interfaces containing method signatures to exclude when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes', 'excludeTypes' should be used.
+     * If interfaces is true (the default), you will need to manually supply any methods excluded
+     * from delegation that are required for the interface.
+     * @since 2.3.0
+     */
+    Class[] excludeTypes() default {};
+
+    /**
+     * List of method and/or property names to include when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
+     * For convenience, a String with comma separated names
+     * can be used in addition to an array (using Groovy's literal list notation) of String values.
+     * The default value is a special marker value indicating that no includes are defined; all fields
+     * are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
+     * If interfaces is true (the default), you will need to manually supply any methods not included
+     * via delegation that are required for the interface.
+     * @since 2.2.0
+     */
+    String[] includes() default {Undefined.STRING};
+
+    /**
+     * List of interfaces containing method signatures to include when delegating.
+     * Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used.
+     * The default value is a special marker value indicating that no includeTypes are defined.
+     * If interfaces is true (the default), you will need to manually supply any methods excluded
+     * from delegation that are required for the interface.
+     * @since 2.3.0
+     */
+    Class[] includeTypes() default {Undefined.CLASS.class};
+
+    /**
+     * Whether to apply the delegate pattern to all methods, including those with names that are considered internal.
+     *
+     * @return true if owner class should delegate to methods which have internal names
+     * @since 2.5.0
+     */
+    boolean allNames() default false;
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/DelegatesTo.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/DelegatesTo.java b/src/main/groovy/groovy/lang/DelegatesTo.java
new file mode 100644
index 0000000..54a5e36
--- /dev/null
+++ b/src/main/groovy/groovy/lang/DelegatesTo.java
@@ -0,0 +1,96 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation can be used by API or DSL writers to document parameters which accept a closure.
+ * In that case, using this annotation, you can specify what the delegate type of the closure will
+ * be. This is important for IDE support.
+ * <p>
+ * This annotation can also be used to help the type checker ({@link groovy.transform.TypeChecked})
+ * which would not report errors then if the delegate is of the documented type. Of course, it is
+ * also compatible with {@link groovy.transform.CompileStatic}.
+ * <p>
+ * Example:
+ * <pre>
+ * // Document the fact that the delegate of the closure will be an ExecSpec
+ * ExecResult exec(@DelegatesTo(ExecSpec) Closure closure) { ... }
+ * </pre>
+ *
+ * @author Cedric Champeau
+ * @author Peter Niderwieser
+ * @since 2.1.0
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface DelegatesTo {
+    Class value() default Target.class;
+
+    /**
+     * The {@link Closure#resolveStrategy} used by the closure.
+     */
+    int strategy() default Closure.OWNER_FIRST;
+
+    /**
+     * The index of the generic type that will be the type of the closure's delegate.
+     * The generic types are considered with respect to the {@code @DelegatesTo.Target} annotated
+     * parameter for this usage, with the index starting at 0.
+     */
+    int genericTypeIndex() default -1;
+
+    /**
+     * In cases when there are multiple {@code @DelegatesTo.Target} annotated parameters, this
+     * member should be set to the {@link DelegatesTo.Target#value()} of the correct target.
+     */
+    String target() default "";
+
+    /**
+     * The type member should be used when the type of the delegate cannot
+     * be represented with {@link #value()}, {@link #genericTypeIndex()} or
+     * {@link #target()}. In this case, it is possible to use a String to represent
+     * the type, at the cost of potential uncaught errors at compile time if the
+     * type is invalid and increased compile time.
+     *
+     * @return a String representation of a type
+     * @since 2.4.0
+     */
+    String type() default "";
+
+    /**
+     * Parameter annotation used to specify the delegate for a {@code @DelegatesTo} annotated
+     * parameter of the same method.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @java.lang.annotation.Target({ElementType.PARAMETER})
+    public static @interface Target {
+
+        /**
+         * An identifier that should be used to disambiguate targets when there are
+         * multiple {@code @DelegatesTo.Target} annotated parameters.
+         */
+        String value() default "";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/DelegatingMetaClass.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/DelegatingMetaClass.java b/src/main/groovy/groovy/lang/DelegatingMetaClass.java
new file mode 100644
index 0000000..ee2ade9
--- /dev/null
+++ b/src/main/groovy/groovy/lang/DelegatingMetaClass.java
@@ -0,0 +1,308 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * @author John Wilson
+ */
+
+public class DelegatingMetaClass implements MetaClass, MutableMetaClass, GroovyObject {
+    protected MetaClass delegate;
+
+    public DelegatingMetaClass(final MetaClass delegate) {
+        this.delegate = delegate;
+    }
+
+    public DelegatingMetaClass(final Class theClass) {
+        this(GroovySystem.getMetaClassRegistry().getMetaClass(theClass));
+    }
+
+    public boolean isModified() {
+        return this.delegate instanceof MutableMetaClass && ((MutableMetaClass) this.delegate).isModified();
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#addNewInstanceMethod(java.lang.reflect.Method)
+    */
+    public void addNewInstanceMethod(Method method) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addNewInstanceMethod(method);
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#addNewStaticMethod(java.lang.reflect.Method)
+    */
+    public void addNewStaticMethod(Method method) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addNewStaticMethod(method);
+    }
+
+    public void addMetaMethod(MetaMethod metaMethod) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addMetaMethod(metaMethod);
+    }
+
+    public void addMetaBeanProperty(MetaBeanProperty metaBeanProperty) {
+        if (delegate instanceof MutableMetaClass)
+            ((MutableMetaClass) delegate).addMetaBeanProperty(metaBeanProperty);
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#initialize()
+    */
+    public void initialize() {
+        delegate.initialize();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getAttribute(java.lang.Object, java.lang.String)
+     */
+    public Object getAttribute(Object object, String attribute) {
+        return delegate.getAttribute(object, attribute);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getClassNode()
+     */
+    public ClassNode getClassNode() {
+        return delegate.getClassNode();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getMetaMethods()
+     */
+    public List<MetaMethod> getMetaMethods() {
+        return delegate.getMetaMethods();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getMethods()
+     */
+    public List<MetaMethod> getMethods() {
+        return delegate.getMethods();
+    }
+
+    public List<MetaMethod> respondsTo(Object obj, String name, Object[] argTypes) {
+        return delegate.respondsTo(obj, name, argTypes);
+    }
+
+    public List<MetaMethod> respondsTo(Object obj, String name) {
+        return delegate.respondsTo(obj, name);
+    }
+
+    public MetaProperty hasProperty(Object obj, String name) {
+        return delegate.hasProperty(obj, name);
+    }
+
+    /* (non-Javadoc)
+    * @see groovy.lang.MetaClass#getProperties()
+    */
+    public List<MetaProperty> getProperties() {
+        return delegate.getProperties();
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#getProperty(java.lang.Object, java.lang.String)
+     */
+    public Object getProperty(Object object, String property) {
+        return delegate.getProperty(object, property);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeConstructor(java.lang.Object[])
+     */
+    public Object invokeConstructor(Object[] arguments) {
+        return delegate.invokeConstructor(arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeMethod(java.lang.Object, java.lang.String, java.lang.Object)
+     */
+    public Object invokeMethod(Object object, String methodName, Object arguments) {
+        return delegate.invokeMethod(object, methodName, arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeMethod(java.lang.Object, java.lang.String, java.lang.Object[])
+     */
+    public Object invokeMethod(Object object, String methodName, Object[] arguments) {
+        return delegate.invokeMethod(object, methodName, arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#invokeStaticMethod(java.lang.Object, java.lang.String, java.lang.Object[])
+     */
+    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
+        return delegate.invokeStaticMethod(object, methodName, arguments);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#setAttribute(java.lang.Object, java.lang.String, java.lang.Object)
+     */
+    public void setAttribute(Object object, String attribute, Object newValue) {
+        delegate.setAttribute(object, attribute, newValue);
+    }
+
+    /* (non-Javadoc)
+     * @see groovy.lang.MetaClass#setProperty(java.lang.Object, java.lang.String, java.lang.Object)
+     */
+    public void setProperty(Object object, String property, Object newValue) {
+        delegate.setProperty(object, property, newValue);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        return delegate.equals(obj);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+
+    public String toString() {
+        return super.toString() + "[" + delegate.toString() + "]";
+    }
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
+    public MetaMethod pickMethod(String methodName, Class[] arguments) {
+        return delegate.pickMethod(methodName, arguments);
+    }
+
+    public Object getAttribute(Class sender, Object receiver, String messageName, boolean useSuper) {
+        return this.delegate.getAttribute(sender, receiver, messageName, useSuper);
+    }
+
+    public Object getProperty(Class sender, Object receiver, String messageName, boolean useSuper, boolean fromInsideClass) {
+        return this.delegate.getProperty(sender, receiver, messageName, useSuper, fromInsideClass);
+    }
+
+    public MetaProperty getMetaProperty(String name) {
+        return this.delegate.getMetaProperty(name);
+    }
+
+    public MetaMethod getStaticMetaMethod(String name, Object[] args) {
+        return this.delegate.getStaticMetaMethod(name, args);
+    }
+
+    public MetaMethod getStaticMetaMethod(String name, Class[] argTypes) {
+        return this.delegate.getStaticMetaMethod(name, argTypes);
+    }
+
+    public MetaMethod getMetaMethod(String name, Object[] args) {
+        return this.delegate.getMetaMethod(name, args);
+    }
+
+    public Class getTheClass() {
+        return this.delegate.getTheClass();
+    }
+
+    public Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass) {
+        return this.delegate.invokeMethod(sender, receiver, methodName, arguments, isCallToSuper, fromInsideClass);
+    }
+
+    public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
+        return this.delegate.invokeMissingMethod(instance, methodName, arguments);
+    }
+
+    public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
+        return this.delegate.invokeMissingProperty(instance, propertyName, optionalValue, isGetter);
+    }
+
+    public boolean isGroovyObject() {
+        return GroovyObject.class.isAssignableFrom(this.delegate.getTheClass());
+    }
+
+    public void setAttribute(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
+        this.delegate.setAttribute(sender, receiver, messageName, messageValue, useSuper, fromInsideClass);
+    }
+
+    public void setProperty(Class sender, Object receiver, String messageName, Object messageValue, boolean useSuper, boolean fromInsideClass) {
+        this.delegate.setProperty(sender, receiver, messageName, messageValue, useSuper, fromInsideClass);
+    }
+
+    public int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments) {
+        return this.delegate.selectConstructorAndTransformArguments(numberOfConstructors, arguments);
+    }
+
+    public void setAdaptee(MetaClass adaptee) {
+        this.delegate = adaptee;
+    }
+
+    public MetaClass getAdaptee() {
+        return this.delegate;
+    }
+
+    public Object invokeMethod(String name, Object args) {
+        try {
+            return getMetaClass().invokeMethod(this, name, args);
+        }
+        catch (MissingMethodException e) {
+            if (delegate instanceof GroovyObject)
+                return ((GroovyObject) delegate).invokeMethod(name, args);
+            else
+                throw e;
+        }
+    }
+
+    public Object getProperty(String property) {
+        try {
+            return getMetaClass().getProperty(this, property);
+        }
+        catch (MissingPropertyException e) {
+            if (delegate instanceof GroovyObject)
+                return ((GroovyObject) delegate).getProperty(property);
+            else
+                throw e;
+        }
+    }
+
+    public void setProperty(String property, Object newValue) {
+        try {
+            getMetaClass().setProperty(this, property, newValue);
+        }
+        catch (MissingPropertyException e) {
+            if (delegate instanceof GroovyObject)
+                ((GroovyObject) delegate).setProperty(property, newValue);
+            else
+                throw e;
+        }
+    }
+
+    public MetaClass getMetaClass() {
+        return InvokerHelper.getMetaClass(getClass());
+    }
+
+    public void setMetaClass(MetaClass metaClass) {
+        throw new UnsupportedOperationException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/DeprecationException.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/DeprecationException.java b/src/main/groovy/groovy/lang/DeprecationException.java
new file mode 100644
index 0000000..36ad893
--- /dev/null
+++ b/src/main/groovy/groovy/lang/DeprecationException.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+/**
+ * Use this exception to mark a method implementation as being deprecated.
+ *
+ * Use the message to indicate the recommended way of calling the desired functionality.
+ * Make throwing this exception the only line in the method implementation, i.e. unlike
+ * the JavaDoc deprecated feature there is no relay to the new implementation but an early
+ * and deliberate halt of execution ("fail early").
+ *
+ * This exception is supposed to be used in the SNAPSHOT releases only. Before release, all
+ * references to this exception should be resolved and the according methods removed.
+ *
+ * @author Dierk Koenig
+ */
+public class DeprecationException extends RuntimeException {
+
+    public DeprecationException(String message) {
+        super(message);
+    }
+
+    public DeprecationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/0ad8c07c/src/main/groovy/groovy/lang/EmptyRange.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/groovy/lang/EmptyRange.java b/src/main/groovy/groovy/lang/EmptyRange.java
new file mode 100644
index 0000000..b67b32e
--- /dev/null
+++ b/src/main/groovy/groovy/lang/EmptyRange.java
@@ -0,0 +1,214 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 groovy.lang;
+
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Constructing Ranges like 0..&lt;0
+ */
+public class EmptyRange<T extends Comparable> extends AbstractList<T> implements Range<T> {
+
+    /**
+     * The value at which the range originates (may be <code>null</code>).
+     */
+    protected T at;
+
+    /**
+     * Creates a new {@link EmptyRange}.
+     *
+     * @param at the value at which the range starts (may be <code>null</code>).
+     */
+    public EmptyRange(T at) {
+        this.at = at;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public T getFrom() {
+        return at;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public T getTo() {
+        return at;
+    }
+
+    /**
+     * Never true for an empty range.
+     *
+     * @return <code>false</code>
+     */
+    @Override
+    public boolean isReverse() {
+        return false;
+    }
+
+    /**
+     * Never true for an empty range.
+     *
+     * @return <code>false</code>
+     */
+    @Override
+    public boolean containsWithinBounds(Object o) {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String inspect() {
+        return InvokerHelper.inspect(at) + "..<" + InvokerHelper.inspect(at);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString() {
+        return (null == at)
+                ? "null..<null"
+                : at + "..<" + at;
+    }
+
+    /**
+     * Always 0 for an empty range.
+     *
+     * @return 0
+     */
+    @Override
+    public int size() {
+        return 0;
+    }
+
+    /**
+     * Always throws <code>IndexOutOfBoundsException</code> for an empty range.
+     *
+     * @throws IndexOutOfBoundsException always
+     */
+    @Override
+    public T get(int index) {
+        throw new IndexOutOfBoundsException("can't get values from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    @Override
+    public boolean add(T o) {
+        throw new UnsupportedOperationException("cannot add to Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean addAll(int index, Collection<? extends T> c) {
+        throw new UnsupportedOperationException("cannot add to Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean addAll(Collection<? extends T> c) {
+        throw new UnsupportedOperationException("cannot add to Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean remove(Object o) {
+        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public T remove(int index) {
+        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        throw new UnsupportedOperationException("cannot remove from Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        throw new UnsupportedOperationException("cannot retainAll in Empty Ranges");
+    }
+
+    /**
+     * Always throws <code>UnsupportedOperationException</code> for an empty range.
+     *
+     * @throws UnsupportedOperationException
+     */
+    @Override
+    public T set(int index, T element) {
+        throw new UnsupportedOperationException("cannot set in Empty Ranges");
+    }
+
+    /**
+     * Always does nothing for an empty range.
+     */
+    @Override
+    public void step(int step, Closure closure) {
+    }
+
+    /**
+     * Always returns an empty list for an empty range.
+     */
+    @Override
+    public List<T> step(int step) {
+        return new ArrayList<T>();
+    }
+}


Mime
View raw message