Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added lis-commons-io/README.md
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.link_intersystems.io;

import java.io.IOException;

/**
* An {@link java.util.function.Consumer} like interface for I/O related stuff.
*
* @param <T> an I/O type that might raise an {@link IOException}.
*/
@FunctionalInterface
public interface IOConsumer<T> {

/**
* An {@link IOConsumer} that does nothing (<b>no</b> <b>op</b>eration).
*
* @param <T>
* @return
*/
public static <T> IOConsumer<T> noop() {
return t -> {
};
}

public void accept(T t) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.link_intersystems.io.file;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;

import static java.util.Objects.requireNonNull;

public abstract class AbstractFile {

private Path path;

protected AbstractFile(Path path) {
this.path = requireNonNull(path);
}

/**
* @return the {@link Path} of this {@link AbstractFile}.
*/
public Path getPath() {
return path;
}

/**
* Creates this file. This method does nothing, if the file already exists.
*
* @throws IOException
*/
public abstract void create() throws IOException;

/**
* @return the parent file of this file if any or <code>null</code>.
* @throws IOException
*/
public abstract AbstractFile getParent();

public boolean exists() {
return Files.exists(getPath());
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AbstractFile that = (AbstractFile) o;
return Objects.equals(getPath(), that.getPath());
}

@Override
public int hashCode() {
return Objects.hash(getPath());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.link_intersystems.io.file;

import com.link_intersystems.io.IOConsumer;

import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Directory extends AbstractFile {

/**
* Creates a {@link Directory} based on the given {@link File}.
*/
public Directory(File dir) {
this(dir.toPath());
}

/**
* Creates a {@link Directory} based on the given dirpath.
*
* @param dirpath the path of this {@link Directory}.
*/
public Directory(Path dirpath) {
super(dirpath);
}

/**
* {@inheritDoc}
* <p>
* If this directory does not exist, all parent directories that also do not exist
* will be created as well.
*
* @throws IOException
*/
@Override
public void create() throws IOException {
Files.createDirectories(getPath());
}

@Override
public Directory getParent() {
Path parent = getPath().getParent();

if (parent != null) {
return new Directory(parent);
}

return null;
}

/**
* @param directoryRelativePath
* @return the {@link RegularFile} of the given path relative to this directory.
* @throws IOException
*/
public RegularFile file(String directoryRelativePath) throws IOException {
return file(Paths.get(directoryRelativePath));
}

/**
* @param directoryRelativePath
* @return the {@link RegularFile} of the given path relative to this directory.
* @throws IOException
*/
public RegularFile file(Path directoryRelativePath) throws IOException {
return new RegularFile(getPath().resolve(directoryRelativePath));
}

/**
* @return all regular files in this directory.
* @throws IOException
*/
public List<RegularFile> listFiles() throws IOException {
return listFiles(path -> true);
}

/**
* @return all regular files in this directory that match the given file filter.
* @throws IOException
*/
public List<RegularFile> listFiles(DirectoryStream.Filter<Path> fileFilter) throws IOException {
List<RegularFile> files = new ArrayList<>();
forEachFiles(files::add, fileFilter);
return files;
}

/**
* Invokes the given {@link IOConsumer} for each {@link RegularFile} in this directory.
*
* @throws IOException
*/
public void forEachFiles(IOConsumer<RegularFile> fileConsumer) throws IOException {
forEachFiles(fileConsumer, path -> true);
}

/**
* Invokes the given {@link IOConsumer} for each {@link RegularFile} in this directory
* that match the given file filter.
*
* @throws IOException
*/
public void forEachFiles(IOConsumer<RegularFile> fileConsumer, DirectoryStream.Filter<Path> fileFilter) throws IOException {
DirectoryStream.Filter<Path> filter = path -> Files.isRegularFile(path) && fileFilter.accept(path);

try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(getPath(), filter)) {
for (Path path : directoryStream) {
RegularFile regularFile = new RegularFile(path);
fileConsumer.accept(regularFile);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.link_intersystems.io.file;

import com.link_intersystems.io.IOConsumer;

import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.StandardOpenOption.*;

public class RegularFile extends AbstractFile {


/**
* Creates a {@link RegularFile} based on the given {@link File}.
*/
public RegularFile(File file) {
this(file.toPath());
}

/**
* Creates a {@link RegularFile} based on the given filepath.
*
* @param filepath the path of this {@link RegularFile}.
*/
public RegularFile(Path filepath) {
super(filepath);
}

/**
* {@inheritDoc}
* <p>
* If the file is created it will be empty.
* <p>
* You do not have to call this method before any
* {@link #write(IOConsumer, Charset)} or {@link #append(IOConsumer, Charset)}
* invocation, because these methods will also create this file if it does not exist.
*
* @throws IOException
*/
@Override
public void create() throws IOException {
append(IOConsumer.noop());
}

@Override
public Directory getParent() {
Path parent = getPath().getParent();

if (parent != null) {
return new Directory(parent);
}

return null;
}

/**
* Writes the content provided by the {@link Appendable} to this {@link RegularFile} using {@link java.nio.charset.StandardCharsets#UTF_8}.
*
* @see #write(IOConsumer, Charset)
*/
public void write(IOConsumer<Appendable> contentWriter) throws IOException {
write(contentWriter, UTF_8);
}

/**
* Writes the content provided by the {@link Appendable} to this {@link RegularFile} using the specified {@link Charset}.
*
* <ul>
* <li>If parent directories do not exist, they will be created.</li>
* <li>If the file does not exist, it will be created.</li>
* <li>If the file already exists, it will be overwritten.</li>
* <li>If the file is an existent directory, an {@link IOException} is raised.</li>
* </ul>
* <p>
* This method can also be used to create an empty file
*
* <pre>
* RegularFile regularFile = ...;
* regularFile.write({@link IOConsumer#noop()});
* </pre>
*
* @param contentWriter an {@link Appendable} {@link IOConsumer} used to write the content of this file.
* @throws IOException if the file is an existent directory or if the content could not be written.
*/
public void write(IOConsumer<Appendable> contentWriter, Charset charset) throws IOException {
ensureParentDirs();

try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(getPath(), CREATE, TRUNCATE_EXISTING), charset))) {
contentWriter.accept(pw);
}
}

private void ensureParentDirs() throws IOException {
Path filePath = getPath();
Path parentPath = filePath.getParent();
if (parentPath != null && !Files.exists(parentPath)) {
Files.createDirectories(parentPath);
}
}

public void append(IOConsumer<Appendable> contentWriter) throws IOException {
append(contentWriter, UTF_8);
}

/**
* Appends content provided by the {@link Appendable} to this {@link RegularFile} using the specified {@link Charset}.
*
* <ul>
* <li>If parent directories do not exist, they will be created.</li>
* <li>If the file does not exist, it will be created and the content will be appended.</li>
* <li>If the file already exists, the content will be appended.</li>
* <li>If the file is an existent directory an {@link IOException} is raised.</li>
* </ul>
*
* @param contentWriter an {@link Appendable} {@link IOConsumer} used to append to the content of this file.
* @throws IOException if the file is an existent directory or if the content could not be appended.
*/
public void append(IOConsumer<Appendable> contentWriter, Charset charset) throws IOException {
ensureParentDirs();

try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(getPath(), CREATE, APPEND), charset))) {
contentWriter.accept(pw);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.link_intersystems.io.file;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.io.IOException;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.*;

class AbstractFileTest {

private static class TestFile extends AbstractFile {

protected TestFile(Path path) {
super(path);
}

@Override
public void create() {

}

@Override
public AbstractFile getParent() {
return null;
}
}

private AbstractFile abstractFile;

@BeforeEach
void setUp(@TempDir Path tempDir) {
abstractFile = new TestFile(tempDir);
}

@Test
void exists() {
assertTrue(abstractFile.exists());
}

@Test
void testEquals(@TempDir Path unequalPath) {
TestFile equal = new TestFile(abstractFile.getPath());
TestFile unequal = new TestFile(unequalPath);

assertEquals(abstractFile, equal);
assertEquals(equal, abstractFile);
assertNotEquals(equal, unequal);
assertNotEquals(equal, null);
assertNotEquals(equal, "");
}

@Test
void testHashCode() {
TestFile actual = new TestFile(abstractFile.getPath());

assertEquals(abstractFile.hashCode(), actual.hashCode());
}
}
Loading