/*
 * 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.wicket.util.file;

import java.io.File;
import java.io.IOException;

/**
 * Strategy for deleting files.
 * <p>
 * There is more than one way to delete a file. You may want to limit access to certain directories,
 * to only delete directories if they are empty, or maybe to force deletion.
 * <p>
 * This class captures the strategy to use and is designed for user subclassing.
 * 
 * @author Stephen Colebourne
 * @version $Id$
 * @since Commons IO 1.3
 */
public class FileDeleteStrategy
{
	/**
	 * The singleton instance for normal file deletion, which does not permit the deletion of
	 * directories that are not empty.
	 */
	public static final FileDeleteStrategy NORMAL = new FileDeleteStrategy("Normal");

	/** The name of the strategy. */
	private final String name;

	// -----------------------------------------------------------------------
	/**
	 * Restricted constructor.
	 * 
	 * @param name
	 *            the name by which the strategy is known
	 */
	protected FileDeleteStrategy(final String name)
	{
		this.name = name;
	}

	// -----------------------------------------------------------------------
	/**
	 * Deletes the file object, which may be a file or a directory. All <code>IOException</code>s
	 * are caught and false returned instead. If the file does not exist or is null, true is
	 * returned.
	 * <p>
	 * Subclass writers should override {@link #doDelete(File)}, not this method.
	 * 
	 * @param fileToDelete
	 *            the file to delete, null returns true
	 * @return true if the file was deleted, or there was no such file
	 */
	public boolean deleteQuietly(final File fileToDelete)
	{
		if ((fileToDelete == null) || (fileToDelete.exists() == false))
		{
			return true;
		}
		try
		{
			return doDelete(fileToDelete);
		}
		catch (IOException ex)
		{
			return false;
		}
	}

	/**
	 * Deletes the file object, which may be a file or a directory. If the file does not exist, the
	 * method just returns.
	 * <p>
	 * Subclass writers should override {@link #doDelete(File)}, not this method.
	 * 
	 * @param fileToDelete
	 *            the file to delete, not null
	 * @throws NullPointerException
	 *             if the file is null
	 * @throws IOException
	 *             if an error occurs during file deletion
	 */
	public void delete(final File fileToDelete) throws IOException
	{
		if (fileToDelete.exists() && (doDelete(fileToDelete) == false))
		{
			throw new IOException("Deletion failed: " + fileToDelete);
		}
	}

	/**
	 * Actually deletes the file object, which may be a file or a directory.
	 * <p>
	 * This method is designed for subclasses to override. The implementation may return either
	 * false or an <code>IOException</code> when deletion fails. The {@link #delete(File)} and
	 * {@link #deleteQuietly(File)} methods will handle either response appropriately. A check has
	 * been made to ensure that the file will exist.
	 * <p>
	 * This implementation uses {@link File#delete()}.
	 * 
	 * @param fileToDelete
	 *            the file to delete, exists, not null
	 * @return true if the file was deleteds
	 * @throws NullPointerException
	 *             if the file is null
	 * @throws IOException
	 *             if an error occurs during file deletion
	 */
	protected boolean doDelete(final File fileToDelete) throws IOException
	{
		return fileToDelete.delete();
	}

	// -----------------------------------------------------------------------
	/**
	 * Gets a string describing the delete strategy.
	 * 
	 * @return a string describing the delete strategy
	 */
	@Override
	public String toString()
	{
		return "FileDeleteStrategy[" + name + "]";
	}
}