/*
 * 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.commons.lang3.concurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * <p>
 * A class that allows complex initialization operations in a background task.
 * </p>
 * <p>
 * Applications often have to do some expensive initialization steps when they
 * are started, e.g. constructing a connection to a database, reading a
 * configuration file, etc. Doing these things in parallel can enhance
 * performance as the CPU load can be improved. However, when access to the
 * resources initialized in a background thread is actually required,
 * synchronization has to be performed to ensure that their initialization is
 * complete.
 * </p>
 * <p>
 * This abstract base class provides support for this use case. A concrete
 * subclass must implement the {@link #initialize()} method. Here an arbitrary
 * initialization can be implemented, and a result object can be returned. With
 * this method in place the basic usage of this class is as follows (where
 * {@code MyBackgroundInitializer} is a concrete subclass):
 * </p>
 *
 * <pre>
 * MyBackgroundInitializer initializer = new MyBackgroundInitializer();
 * initializer.start();
 * // Now do some other things. Initialization runs in a parallel thread
 * ...
 * // Wait for the end of initialization and access the result object
 * Object result = initializer.get();
 * </pre>
 *
 * <p>
 * After the construction of a {@code BackgroundInitializer} object its
 * {@link #start()} method has to be called. This starts the background
 * processing. The application can now continue to do other things. When it
 * needs access to the object produced by the {@code BackgroundInitializer} it
 * calls its {@link #get()} method. If initialization is already complete,
 * {@link #get()} returns the result object immediately. Otherwise it blocks
 * until the result object is fully constructed.
 * </p>
 * <p>
 * {@code BackgroundInitializer} is a thin wrapper around a {@code Future}
 * object and uses an {@code ExecutorService} for running the background
 * initialization task. It is possible to pass in an {@code ExecutorService} at
 * construction time or set one using {@code setExternalExecutor()} before
 * {@code start()} was called. Then this object is used to spawn the background
 * task. If no {@code ExecutorService} has been provided, {@code
 * BackgroundInitializer} creates a temporary {@code ExecutorService} and
 * destroys it when initialization is complete.
 * </p>
 * <p>
 * The methods provided by {@code BackgroundInitializer} provide for minimal
 * interaction with the wrapped {@code Future} object. It is also possible to
 * obtain the {@code Future} object directly. Then the enhanced functionality
 * offered by {@code Future} can be used, e.g. to check whether the background
 * operation is complete or to cancel the operation.
 * </p>
 *
 * @since 3.0
 * @param <T> the type of the object managed by this initializer class
 */
public abstract class BackgroundInitializer<T> implements
        ConcurrentInitializer<T> {
    /** The external executor service for executing tasks. */
    private ExecutorService externalExecutor; // @GuardedBy("this")

    /** A reference to the executor service that is actually used. */
    private ExecutorService executor; // @GuardedBy("this")

    /** Stores the handle to the background task. */
    private Future<T> future;  // @GuardedBy("this")

    /**
     * Creates a new instance of {@code BackgroundInitializer}. No external
     * {@code ExecutorService} is used.
     */
    protected BackgroundInitializer() {
        this(null);
    }

    /**
     * Creates a new instance of {@code BackgroundInitializer} and initializes
     * it with the given {@code ExecutorService}. If the {@code ExecutorService}
     * is not null, the background task for initializing this object will be
     * scheduled at this service. Otherwise a new temporary {@code
     * ExecutorService} is created.
     *
     * @param exec an external {@code ExecutorService} to be used for task
     * execution
     */
    protected BackgroundInitializer(final ExecutorService exec) {
        setExternalExecutor(exec);
    }

    /**
     * Returns the external {@code ExecutorService} to be used by this class.
     *
     * @return the {@code ExecutorService}
     */
    public final synchronized ExecutorService getExternalExecutor() {
        return externalExecutor;
    }

    /**
     * Returns a flag whether this {@code BackgroundInitializer} has already
     * been started.
     *
     * @return a flag whether the {@link #start()} method has already been
     * called
     */
    public synchronized boolean isStarted() {
        return future != null;
    }

    /**
     * Sets an {@code ExecutorService} to be used by this class. The {@code
     * ExecutorService} passed to this method is used for executing the
     * background task. Thus it is possible to re-use an already existing
     * {@code ExecutorService} or to use a specially configured one. If no
     * {@code ExecutorService} is set, this instance creates a temporary one and
     * destroys it after background initialization is complete. Note that this
     * method must be called before {@link #start()}; otherwise an exception is
     * thrown.
     *
     * @param externalExecutor the {@code ExecutorService} to be used
     * @throws IllegalStateException if this initializer has already been
     * started
     */
    public final synchronized void setExternalExecutor(
            final ExecutorService externalExecutor) {
        if (isStarted()) {
            throw new IllegalStateException(
                    "Cannot set ExecutorService after start()!");
        }

        this.externalExecutor = externalExecutor;
    }

    /**
     * Starts the background initialization. With this method the initializer
     * becomes active and invokes the {@link #initialize()} method in a
     * background task. A {@code BackgroundInitializer} can be started exactly
     * once. The return value of this method determines whether the start was
     * successful: only the first invocation of this method returns <b>true</b>,
     * following invocations will return <b>false</b>.
     *
     * @return a flag whether the initializer could be started successfully
     */
    public synchronized boolean start() {
        // Not yet started?
        if (!isStarted()) {

            // Determine the executor to use and whether a temporary one has to
            // be created
            final ExecutorService tempExec;
            executor = getExternalExecutor();
            if (executor == null) {
                executor = tempExec = createExecutor();
            } else {
                tempExec = null;
            }

            future = executor.submit(createTask(tempExec));

            return true;
        }

        return false;
    }

    /**
     * Returns the result of the background initialization. This method blocks
     * until initialization is complete. If the background processing caused a
     * runtime exception, it is directly thrown by this method. Checked
     * exceptions, including {@code InterruptedException} are wrapped in a
     * {@link ConcurrentException}. Calling this method before {@link #start()}
     * was called causes an {@code IllegalStateException} exception to be
     * thrown.
     *
     * @return the object produced by this initializer
     * @throws ConcurrentException if a checked exception occurred during
     * background processing
     * @throws IllegalStateException if {@link #start()} has not been called
     */
    @Override
    public T get() throws ConcurrentException {
        try {
            return getFuture().get();
        } catch (final ExecutionException execex) {
            ConcurrentUtils.handleCause(execex);
            return null; // should not be reached
        } catch (final InterruptedException iex) {
            // reset interrupted state
            Thread.currentThread().interrupt();
            throw new ConcurrentException(iex);
        }
    }

    /**
     * Returns the {@code Future} object that was created when {@link #start()}
     * was called. Therefore this method can only be called after {@code
     * start()}.
     *
     * @return the {@code Future} object wrapped by this initializer
     * @throws IllegalStateException if {@link #start()} has not been called
     */
    public synchronized Future<T> getFuture() {
        if (future == null) {
            throw new IllegalStateException("start() must be called first!");
        }

        return future;
    }

    /**
     * Returns the {@code ExecutorService} that is actually used for executing
     * the background task. This method can be called after {@link #start()}
     * (before {@code start()} it returns <b>null</b>). If an external executor
     * was set, this is also the active executor. Otherwise this method returns
     * the temporary executor that was created by this object.
     *
     * @return the {@code ExecutorService} for executing the background task
     */
    protected final synchronized ExecutorService getActiveExecutor() {
        return executor;
    }

    /**
     * Returns the number of background tasks to be created for this
     * initializer. This information is evaluated when a temporary {@code
     * ExecutorService} is created. This base implementation returns 1. Derived
     * classes that do more complex background processing can override it. This
     * method is called from a synchronized block by the {@link #start()}
     * method. Therefore overriding methods should be careful with obtaining
     * other locks and return as fast as possible.
     *
     * @return the number of background tasks required by this initializer
     */
    protected int getTaskCount() {
        return 1;
    }

    /**
     * Performs the initialization. This method is called in a background task
     * when this {@code BackgroundInitializer} is started. It must be
     * implemented by a concrete subclass. An implementation is free to perform
     * arbitrary initialization. The object returned by this method can be
     * queried using the {@link #get()} method.
     *
     * @return a result object
     * @throws Exception if an error occurs
     */
    protected abstract T initialize() throws Exception;

    /**
     * Creates a task for the background initialization. The {@code Callable}
     * object returned by this method is passed to the {@code ExecutorService}.
     * This implementation returns a task that invokes the {@link #initialize()}
     * method. If a temporary {@code ExecutorService} is used, it is destroyed
     * at the end of the task.
     *
     * @param execDestroy the {@code ExecutorService} to be destroyed by the
     * task
     * @return a task for the background initialization
     */
    private Callable<T> createTask(final ExecutorService execDestroy) {
        return new InitializationTask(execDestroy);
    }

    /**
     * Creates the {@code ExecutorService} to be used. This method is called if
     * no {@code ExecutorService} was provided at construction time.
     *
     * @return the {@code ExecutorService} to be used
     */
    private ExecutorService createExecutor() {
        return Executors.newFixedThreadPool(getTaskCount());
    }

    private class InitializationTask implements Callable<T> {
        /** Stores the executor service to be destroyed at the end. */
        private final ExecutorService execFinally;

        /**
         * Creates a new instance of {@code InitializationTask} and initializes
         * it with the {@code ExecutorService} to be destroyed at the end.
         *
         * @param exec the {@code ExecutorService}
         */
        InitializationTask(final ExecutorService exec) {
            execFinally = exec;
        }

        /**
         * Initiates initialization and returns the result.
         *
         * @return the result object
         * @throws Exception if an error occurs
         */
        @Override
        public T call() throws Exception {
            try {
                return initialize();
            } finally {
                if (execFinally != null) {
                    execFinally.shutdown();
                }
            }
        }
    }
}
