/*
 * 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 org.apache.geode.cache.execute;

import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.LowMemoryException;

/**
 * Provides methods to build the context for the execution of a {@link Function} . A Context
 * describes the environment in which the {@link Execution} will take place.
 * <p>
 * This interface is implemented by GemFire. To obtain an instance of it use
 * {@link FunctionService}.
 *
 * @param <IN> The type of the argument passed into the function, if any
 * @param <OUT> The type of results sent by the function
 * @param <AGG> The type of the aggregated result returned by the ResultCollector
 *
 * @since GemFire 6.0
 *
 * @see FunctionService
 * @see Function
 */
public interface Execution<IN, OUT, AGG> {

  /**
   * Specifies a data filter of routing objects for selecting the GemFire members to execute the
   * function on.
   * <p>
   * Applicable only for regions with {@link DataPolicy#PARTITION} DataPolicy. If the filter is
   * null, it will execute on all data of the region.
   *
   * @param filter Set defining the data filter to be used for executing the function
   * @return an Execution with the filter
   * @throws IllegalArgumentException if filter passed is null.
   * @throws UnsupportedOperationException if not called after
   *         {@link FunctionService#onRegion(org.apache.geode.cache.Region)}
   * @since GemFire 6.0
   */
  Execution<IN, OUT, AGG> withFilter(Set<?> filter);

  /**
   * Specifies the user data passed to the function when it is executed. The function can retrieve
   * these arguments using {@link FunctionContext#getArguments()}
   *
   * @param args user data passed to the function execution
   * @return an Execution with args
   * @throws IllegalArgumentException if the input parameter is null
   * @since Geode 1.2
   *
   */
  Execution<IN, OUT, AGG> setArguments(IN args);

  /**
   * Specifies the user data passed to the function when it is executed. The function can retrieve
   * these arguments using {@link FunctionContext#getArguments()}
   *
   * @param args user data passed to the function execution
   * @return an Execution with args
   * @throws IllegalArgumentException if the input parameter is null
   * @since GemFire 6.0
   * @deprecated use {@link #setArguments(Object)} instead
   *
   */
  @Deprecated
  Execution<IN, OUT, AGG> withArgs(IN args);

  /**
   * Specifies the {@link ResultCollector} that will receive the results after the function has been
   * executed. Collector will receive results as they are sent from the
   * {@link Function#execute(FunctionContext)} using {@link ResultSender}.
   *
   * @param rc The {@link ResultCollector} that will receive the results
   * @return an Execution with a collector
   * @throws IllegalArgumentException if {@link ResultCollector} is null
   * @see ResultCollector
   * @since GemFire 6.0
   */
  Execution<IN, OUT, AGG> withCollector(ResultCollector<OUT, AGG> rc);

  /**
   * Executes the function using its {@linkplain Function#getId() id}.
   * When executed from a client, it blocks until all results have been received
   * or the global timeout (gemfire.CLIENT_FUNCTION_TIMEOUT Java property), if set, has expired.
   * <p>
   * {@link Function#execute(FunctionContext)} is called on the instance retrieved using
   * {@link FunctionService#getFunction(String)} on the executing member.
   *
   * @param functionId id of the function to execute
   * @throws LowMemoryException if the {@link Function#optimizeForWrite()} returns true and there is
   *         a low memory condition
   * @return ResultCollector to retrieve the results received. This is different object than the
   *         ResultCollector provided in {@link Execution#withCollector(ResultCollector)}. User has
   *         to use this reference to retrieve results.
   *
   * @since GemFire 6.0
   */
  ResultCollector<OUT, AGG> execute(String functionId) throws FunctionException;

  /**
   * Executes the function using its {@linkplain Function#getId() id} with the specified timeout.
   * It blocks until all results have been received or the timeout has expired.
   * <p>
   * {@link Function#execute(FunctionContext)} is called on the instance retrieved using
   * {@link FunctionService#getFunction(String)} on the executing member.
   *
   * @param functionId id of the function to execute
   * @param timeout time to wait for the operation to finish before timing out
   * @param unit timeout unit
   * @return ResultCollector to retrieve the results received. This is different object than the
   *         ResultCollector provided in {@link Execution#withCollector(ResultCollector)}. User has
   *         to use this reference to retrieve results.
   *
   * @since Geode 1.11
   */
  ResultCollector<OUT, AGG> execute(String functionId, long timeout, TimeUnit unit)
      throws FunctionException;

  /**
   * Executes the function instance provided.
   * When executed from a client, it blocks until all results have been received
   * or the global timeout (gemfire.CLIENT_FUNCTION_TIMEOUT Java property), if set, has expired.
   * <p>
   * {@link Function#execute(FunctionContext)} is called on the de-serialized instance on the
   * executing member.
   *
   * @param function instance to execute
   * @throws LowMemoryException if the {@link Function#optimizeForWrite()} returns true and there is
   *         a low memory condition
   * @return ResultCollector to retrieve the results received. This is different object than the
   *         ResultCollector provided in {@link Execution#withCollector(ResultCollector)}. User has
   *         to use this reference to retrieve results.
   *
   * @since GemFire 6.0
   */
  ResultCollector<OUT, AGG> execute(Function function) throws FunctionException;

  /**
   * Executes the function instance provided.
   * It blocks until all results have been received or the timeout has expired.
   * <p>
   * {@link Function#execute(FunctionContext)} is called on the de-serialized instance on the
   * executing member.
   *
   * @param function instance to execute
   * @param timeout time to wait for the operation to finish before timing out
   * @param unit timeout unit
   * @throws LowMemoryException if the {@link Function#optimizeForWrite()} returns true and there is
   *         a low memory condition
   * @return ResultCollector to retrieve the results received. This is different object than the
   *         ResultCollector provided in {@link Execution#withCollector(ResultCollector)}. User has
   *         to use this reference to retrieve results.
   *
   * @since Geode 1.11
   */
  ResultCollector<OUT, AGG> execute(Function function, long timeout, TimeUnit unit)
      throws FunctionException;

}
