/*
 * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> and
 * other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v1.0 which accompanies this
 * distribution, is reproduced below, and is available at
 * http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package org.eclipse.jgit.api;

import java.text.MessageFormat;
import java.util.concurrent.Callable;

import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.lib.Repository;

/**
 * Common superclass of all commands in the package {@code org.eclipse.jgit.api}
 * <p>
 * This class ensures that all commands fulfill the {@link Callable} interface.
 * It also has a property {@link #repo} holding a reference to the git
 * {@link Repository} this command should work with.
 * <p>
 * Finally this class stores a state telling whether it is allowed to call
 * {@link #call()} on this instance. Instances of {@link GitCommand} can only be
 * used for one single successful call to {@link #call()}. Afterwards this
 * instance may not be used anymore to set/modify any properties or to call
 * {@link #call()} again. This is achieved by setting the {@link #callable}
 * property to false after the successful execution of {@link #call()} and to
 * check the state (by calling {@link #checkCallable()}) before setting of
 * properties and inside {@link #call()}.
 *
 * @param <T>
 *            the return type which is expected from {@link #call()}
 */
public abstract class GitCommand<T> implements Callable<T> {
	/** The repository this command is working with */
	final protected Repository repo;

	/**
	 * a state which tells whether it is allowed to call {@link #call()} on this
	 * instance.
	 */
	private boolean callable = true;

	/**
	 * Creates a new command which interacts with a single repository
	 *
	 * @param repo
	 *            the {@link Repository} this command should interact with
	 */
	protected GitCommand(Repository repo) {
		this.repo = repo;
	}

	/**
	 * @return the {@link Repository} this command is interacting with
	 */
	public Repository getRepository() {
		return repo;
	}

	/**
	 * Set's the state which tells whether it is allowed to call {@link #call()}
	 * on this instance. {@link #checkCallable()} will throw an exception when
	 * called and this property is set to {@code false}
	 *
	 * @param callable
	 *            if <code>true</code> it is allowed to call {@link #call()} on
	 *            this instance.
	 */
	protected void setCallable(boolean callable) {
		this.callable = callable;
	}

	/**
	 * Checks that the property {@link #callable} is {@code true}. If not then
	 * an {@link IllegalStateException} is thrown
	 *
	 * @throws IllegalStateException
	 *             when this method is called and the property {@link #callable}
	 *             is {@code false}
	 */
	protected void checkCallable() {
		if (!callable)
			throw new IllegalStateException(MessageFormat.format(
					JGitText.get().commandWasCalledInTheWrongState
					, this.getClass().getName()));
	}
}
