// Path: src/main/java/com/github/fzakaria/waterflow/Activities.java
// public abstract class Activities {
// 
//     protected final Logger log = LoggerFactory.getLogger(getClass());
// 
//     @Nullable
//     private ActivityContext activityContext;
// 
//     public ActivityContext activityContext() {
//         return activityContext;
//     }
// 
//     public Activities activityContext(ActivityContext activityContext) {
//         this.activityContext = activityContext;
//         return this;
//     }
// 
//     /**
//      * Record a heartbeat on SWF.
//      * @param details information to be recorded
//      */
//     protected void recordHeartbeat(String details) {
//         Preconditions.checkNotNull(activityContext, "ActivityContext should have been set.");
//         final String taskToken = activityContext().task().getTaskToken();
//         try {
//             final RecordActivityTaskHeartbeatRequest request =
//                     RecordActivityTaskHeartbeatRequestBuilder.builder()
//                             .taskToken(taskToken).details(Details.of(details)).build();
//             activityContext().service().recordActivityTaskHeartbeat(request);
//         } catch (Throwable e) {
//             log.warn("Failed to record heartbeat: " + taskToken + ", " + details, e);
//             throw e;
//         }
//     }
// 
// }
// 
// Path: src/main/java/com/github/fzakaria/waterflow/converter/DataConverter.java
// public interface DataConverter {
// 
//     /**
//      * Given any input object return the String representation of it
//      * @param input The object to serialize
//      * @return The serialized string
//      * @throws DataConverterException if anything goes awry
//      */
//     String toData(Object input) throws DataConverterException;
// 
//     /**
//      * Given a input string and a target type, coerce the string to it
//      * @param input The serialized version of the final output
//      * @param type The type to be converted to
//      * @return The deserialized result
//      * @throws DataConverterException if anything goes awry
//      */
//     <T> T fromData(String input, Type type) throws DataConverterException;
// 
// }


import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.model.ActivityTask;
import com.github.fzakaria.waterflow.Activities;
import com.github.fzakaria.waterflow.ImmutableActivityContext;
import com.github.fzakaria.waterflow.converter.DataConverter;
import org.immutables.value.Value;
import java.lang.reflect.Method;
import static java.lang.String.format;
package com.github.fzakaria.waterflow.activity;




/**
 * The class/interface that is responsible from figuring out what implements the
 * specific {@link ActivityTask}\
 * This implementation is designed for use with {@link ActivityMethod} and expects
 * the input of the {@link ActivityTask} to be a {@link Object[]}
 */
@Value.Immutable
public abstract class ActivityInvoker {

    public abstract AmazonSimpleWorkflow service();
    public abstract ActivityMethod activityMethod();
    public abstract Method method();
    public abstract Activities instance();
    public abstract DataConverter dataConverter();

    /**
     * Given a {@link ActivityTask} execute matching {@link ActivityMethod}
     * The input of the ActivityTask must be a Object[]
     * @return The result of the {@link ActivityMethod} serialized
     */
    public String invoke(ActivityTask task) {
// Path: src/main/java/com/github/fzakaria/waterflow/Activities.java
// public abstract class Activities {
// 
//     protected final Logger log = LoggerFactory.getLogger(getClass());
// 
//     @Nullable
//     private ActivityContext activityContext;
// 
//     public ActivityContext activityContext() {
//         return activityContext;
//     }
// 
//     public Activities activityContext(ActivityContext activityContext) {
//         this.activityContext = activityContext;
//         return this;
//     }
// 
//     /**
//      * Record a heartbeat on SWF.
//      * @param details information to be recorded
//      */
//     protected void recordHeartbeat(String details) {
//         Preconditions.checkNotNull(activityContext, "ActivityContext should have been set.");
//         final String taskToken = activityContext().task().getTaskToken();
//         try {
//             final RecordActivityTaskHeartbeatRequest request =
//                     RecordActivityTaskHeartbeatRequestBuilder.builder()
//                             .taskToken(taskToken).details(Details.of(details)).build();
//             activityContext().service().recordActivityTaskHeartbeat(request);
//         } catch (Throwable e) {
//             log.warn("Failed to record heartbeat: " + taskToken + ", " + details, e);
//             throw e;
//         }
//     }
// 
// }
// 
// Path: src/main/java/com/github/fzakaria/waterflow/converter/DataConverter.java
// public interface DataConverter {
// 
//     /**
//      * Given any input object return the String representation of it
//      * @param input The object to serialize
//      * @return The serialized string
//      * @throws DataConverterException if anything goes awry
//      */
//     String toData(Object input) throws DataConverterException;
// 
//     /**
//      * Given a input string and a target type, coerce the string to it
//      * @param input The serialized version of the final output
//      * @param type The type to be converted to
//      * @return The deserialized result
//      * @throws DataConverterException if anything goes awry
//      */
//     <T> T fromData(String input, Type type) throws DataConverterException;
// 
// }


// Path: src/main/java/com/github/fzakaria/waterflow/activity/ActivityInvoker.java
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.model.ActivityTask;
import com.github.fzakaria.waterflow.Activities;
import com.github.fzakaria.waterflow.ImmutableActivityContext;
import com.github.fzakaria.waterflow.converter.DataConverter;
import org.immutables.value.Value;
import java.lang.reflect.Method;
import static java.lang.String.format;

package com.github.fzakaria.waterflow.activity;




/**
 * The class/interface that is responsible from figuring out what implements the
 * specific {@link ActivityTask}\
 * This implementation is designed for use with {@link ActivityMethod} and expects
 * the input of the {@link ActivityTask} to be a {@link Object[]}
 */
@Value.Immutable
public abstract class ActivityInvoker {

    public abstract AmazonSimpleWorkflow service();
    public abstract ActivityMethod activityMethod();
    public abstract Method method();
    public abstract Activities instance();
    public abstract DataConverter dataConverter();

    /**
     * Given a {@link ActivityTask} execute matching {@link ActivityMethod}
     * The input of the ActivityTask must be a Object[]
     * @return The result of the {@link ActivityMethod} serialized
     */
    public String invoke(ActivityTask task) {
        final ImmutableActivityContext context =