/*
 * Copyright 2012 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.gradle.api.internal;

import org.gradle.api.Action;
import org.gradle.api.Transformer;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public abstract class Actions {

    /**
     * Creates an action implementation that simply does nothing.
     *
     * A new action instance is created each time.
     *
     * @param <T> The parameter type
     * @return An action object with an empty implementation
     */
    public static <T> Action<T> doNothing() {
        return new Action<T>() {
            public void execute(T t) {}
        };
    }

    /**
     * Creates an action that will call each of the given actions in order.
     *
     * @param actions The actions to make a composite of.
     * @param <T> The type of the object that action is for
     * @return The composite action.
     */
    public static <T> Action<T> composite(Action<? super T>... actions) {
        final List<Action<? super T>> actionsCopy = new ArrayList<Action<? super T>>(actions.length);
        Collections.addAll(actionsCopy, actions);

        return new Action<T>() {
            public void execute(final T item) {
                for (Action<? super T> action : actionsCopy) {
                    action.execute(item);
                }
            }
        };
    }

    /**
     * Creates a new composite action, where the argument is first transformed.
     *
     * @param action The action.
     * @param transformer The transformer to transform the argument with
     * @param <T> The type the action is expecting (that the argument is transformed to)
     * @param <I> The type of the original argument
     * @return An action that transforms an object of type I to type O to give to the given action
     */
    public static <T, I> Action<I> transformBefore(final Action<? super T> action, final Transformer<T, I> transformer) {
        return new Action<I>() {
            public void execute(I thing) {
                T transformed = transformer.transform(thing);
                action.execute(transformed);
            }
        };
    }

    /**
     * Adapts an action to a different type by casting the object before giving it to the action.
     *
     * @param actionType The type the action is expecting
     * @param action The action
     * @param <T> The type the action is expecting
     * @param <I> The type before casting
     * @return An action that casts the object to the given type before giving it to the given action
     */
    public static <T, I> Action<I> castBefore(final Class<T> actionType, final Action<? super T> action) {
        return transformBefore(action, new CastingTransformer<T, I>(actionType));
    }

}

@@ -710,16 +710,45 @@
 ormer;%0A%0A
+import java.io.Serializable;%0A
 import j
@@ -1156,32 +1156,36 @@
      return new 
+Null
 Action%3CT%3E() %7B%0A  
@@ -1171,39 +1171,117 @@
  NullAction%3CT%3E()
- %7B%0A    
+;%0A    %7D%0A%0A    private static class NullAction%3CT%3E implements Action%3CT%3E, Serializable %7B%0A
         public v
@@ -1300,27 +1300,16 @@
 T t) %7B%7D%0A
-        %7D;%0A
     %7D%0A%0A 
@@ -1787,17 +1787,16 @@
 tions);%0A
-%0A
         
@@ -1802,24 +1802,33 @@
  return new 
+Composite
 Action%3CT%3E() 
@@ -1825,24 +1825,281 @@
 tion%3CT%3E(
-) %7B%0A    
+actionsCopy);%0A   %7D%0A%0A    private static class CompositeAction%3CT%3E implements Action%3CT%3E %7B%0A        private final Iterable%3CAction%3C? super T%3E%3E actions;%0A%0A        private CompositeAction(Iterable%3CAction%3C? super T%3E%3E actions) %7B%0A            this.actions = actions;%0A        %7D%0A%0A
         
@@ -2118,22 +2118,16 @@
 execute(
-final 
 T item) 
@@ -2124,28 +2124,24 @@
 e(T item) %7B%0A
-    
             
@@ -2183,20 +2183,12 @@
 ions
-Copy) %7B%0A    
+) %7B%0A
     
@@ -2225,26 +2225,8 @@
 m);%0A
-                %7D%0A
     
@@ -2236,33 +2236,32 @@
      %7D%0A        %7D
-;
 %0A    %7D%0A%0A    /**%0A
@@ -2846,26 +2846,441 @@
 new 
-Action%3CI%3E() %7B%0A    
+TransformingActionAdapter%3CT, I%3E(transformer, action);%0A    %7D%0A%0A    private static class TransformingActionAdapter%3CT, I%3E implements Action%3CI%3E %7B%0A        private final Transformer%3CT, I%3E transformer;%0A        private final Action%3C? super T%3E action;%0A%0A        private TransformingActionAdapter(Transformer%3CT, I%3E transformer, Action%3C? super T%3E action) %7B%0A            this.transformer = transformer;%0A            this.action = action;%0A        %7D%0A%0A
     
@@ -3310,28 +3310,24 @@
 (I thing) %7B%0A
-    
             
@@ -3376,36 +3376,32 @@
 g);%0A            
-    
 action.execute(t
@@ -3425,24 +3425,9 @@
     
-  
-  %7D%0A        %7D;
+%7D
 %0A   

Make Actions.doNothing() Serializable and use private static classes instead of inners so they are easier to identify in stacktraces.