/*
 *  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
 *
 *      https://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.ivy.plugins.repository;

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.ivy.core.module.descriptor.Artifact;

/**
 * Represents a collection of resources available to Ivy. Ivy uses one or more repositories as both
 * a source of resources for Ivy enabled build systems and as a distribution center for resources
 * generated by Ivy enabled build systems.
 * <p>A repository supports the following fundamental operations</p>
 * <ul>
 * <li>retrieving a resource from the repository.</li>
 * <li>transferring a resource to the repository.</li>
 * <li>retrieving a listing of resources.</li>
 * </ul>
 * <h3>Resource Retrieval</h3>
 * <p>{@link #get} retrieves a resource specified by a provided identifier creating a new file.</p>
 * <h3>Resource Publication</h3>
 * <p>{@link #put} transfers a file to the repository.</p>
 * <h2>resource Listing</h2>
 * <p>
 * {@link #list} returns a listing of file like objects belonging to a specified parent directory.
 * </p>
 */
public interface Repository {

    /**
     * Return the resource associated with a specified identifier. If the resource does not exist,
     * it should return a Resource with exists() returning false. An IOException should only be
     * thrown when a real IO problem occurs, like the impossibility to connect to a server.
     *
     * @param source
     *            A string identifying the resource.
     * @return The resource associated with the resource identifier.
     * @throws IOException
     *             On error while trying to get resource.
     */
    Resource getResource(String source) throws IOException;

    /**
     * Fetch a resource from the repository.
     *
     * @param source
     *            A string identifying the resource to be fetched.
     * @param destination
     *            Where to place the fetched resource.
     * @throws IOException
     *             On retrieval failure.
     */
    void get(String source, File destination) throws IOException;

    /**
     * Transfer a resource to the repository
     *
     * @param artifact
     *            The artifact to be transferred.
     * @param source
     *            The local file to be transferred.
     * @param destination
     *            Where to transfer the resource.
     * @param overwrite
     *            Whether the transfer should overwrite an existing resource.
     * @throws IOException
     *             On publication failure.
     */
    void put(Artifact artifact, File source, String destination, boolean overwrite)
            throws IOException;

    /**
     * Return a listing of resources names
     *
     * @param parent
     *            The parent directory from which to generate the listing.
     * @return A listing of the parent directory's file content
     * @throws IOException
     *             On listing failure.
     */
    List<String> list(String parent) throws IOException;

    /**
     * Add a listener to the repository.
     *
     * @param listener
     *            The listener to attach to the repository.
     */
    void addTransferListener(TransferListener listener);

    /**
     * Remove a listener on the repository
     *
     * @param listener
     *            The listener to remove
     */
    void removeTransferListener(TransferListener listener);

    /**
     * Determine if a given listener is attached to the repository.
     *
     * @param listener
     *            The listener being queried
     * @return <code>true</code> if the provided listener is attached to the repository,
     *         <code>false</code> if not.
     */
    boolean hasTransferListener(TransferListener listener);

    /**
     * Get the repository's file separator string.
     *
     * @return The repository's file separator delimiter
     */
    String getFileSeparator();

    /**
     * Normalize a string.
     *
     * @param source
     *            The string to normalize.
     * @return The normalized string.
     */
    String standardize(String source);

    /**
     * Return the name of the repository
     *
     * @return String name
     */
    String getName();
}
