package eu.fbk.knowledgestore.filestore;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import eu.fbk.knowledgestore.data.Stream;
import eu.fbk.knowledgestore.runtime.Component;
/**
* A storage for resource files, supporting CRUD operations.
* <p>
* A {@code FileStore} abstracts the way resource files are stored in the KnowledgeStore allowing
* different implementations to be plugged in. A {@code FileStore} stores a list of files each
* identified by a filename, with no (visible) directory structure. Files can be listed (
* {@link #list()}), written ({@link #write(String)}), read ( {@link #read(String)}) or deleted (
* {@link #delete(String)}), but not modified after they are written the first time. Note that a
* {@code FileStore} obeys the general contract and lifecycle of {@link Component}.
* </p>
*/
public interface FileStore extends Component {
/**
* Read a file stored on the {@code FileStore}. The method returns an {@code InputStream} over
* the content of the file, starting from its first byte. Sequential access and forward
* seeking ( {@link InputStream#skip(long)}) are supported. Note that multiple concurrent read
* operations on the same file are allowed.
*
* @param filename
* the name of the file
* @return an {@code InputStream} allowing access to the content of the file
* @throws FileMissingException
* in case no file exists for the name specified, resulting either from a caller
* error or from an external modification (deletion) to the {@code FileStore}
* @throws IOException
* in case the file cannot be accessed for whatever reason, with no implication on
* the fact that the file exists or does not exist (e.g., the whole
* {@code FileStore} may temporarily be not accessible)
*/
InputStream read(String filename) throws FileMissingException, IOException;
/**
* Writes a new file to the {@code FileStore}. The method creates a file with the name
* specified, and returns an {@code OutputStream} that can be used to write the content of the
* file. Writing is completed by closing that stream, which forces written data to be flushed
* to disk; errors in writing the file may result in the stream being forcedly closed and a
* truncated file to be written. The file being written may be listed by {@link #list()}
* (depending on the {@code FileStore} implementation) but should not be accessed for read or
* deletion until writing is completed; the consequences of doing so are not specified.
*
* @param filename
* the name of the file
* @return an {@code OutputStream} where the content of the file can be written to
* @throws FileExistsException
* in case a file with the same name already exists, resulting either from a
* caller error or from an external modification (file creation) to the
* {@code FileStore}.
* @throws IOException
* in case the file cannot be created for whatever reason, with no implication on
* the fact that another file with the same name already exists
*/
OutputStream write(String filename) throws FileExistsException, IOException;
/**
* Deletes a file on the {@code FileStore}. An exception is thrown if the file specified does
* not exist. After the method returns, the file cannot be accessed anymore from
* {@link #read(String)} or {@link #delete(String)}. Deleting a file being read is allowed and
* eventually results in the deletion of the file; whether the concurrent read operation fails
* or is permitted to complete is an implementation detail.
*
* @param filename
* the name of the file
* @throws FileMissingException
* in case the file specified does not exist, possibly because of an external
* modification to the {@code FileStore}
* @throws IOException
* in case the file cannot be accessed for whatever reason, with no implication on
* the fact that the file specified actually exists
*/
void delete(String filename) throws FileMissingException, IOException;
/**
* Lists all the files stored on the {@code FileStore}. The method returns a {@code Stream}
* supporting streaming access to the names of the files stored in the {@code FileStore}.
* Concurrent modifications to the {@code FileStore} ({@link #write(String)},
* {@link #delete(String)}) may be supported, depending on the implementation: in that case,
* the stream may either reflect the status before or after the concurrent modification.
*
* @return a stream over the names of the files stored in the {@code FileStore}
* @throws IOException
* in case of failure, for whatever reason
*/
Stream<String> list() throws IOException;
}