All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.thorbenkuck.keller.nio.files.NativeFileReader Maven / Gradle / Ivy

package com.github.thorbenkuck.keller.nio.files;

import com.github.thorbenkuck.keller.observers.ObservableValue;
import com.github.thorbenkuck.keller.pipe.Pipeline;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.stream.Stream;

final class NativeFileReader implements FileReader {

	private final ObservableValue target = ObservableValue.empty();
	private final Pipeline lineProcessor = Pipeline.unifiedCreation();
	private int currentLine = 0;

	private void setEmpty() {
		synchronized (target) {
			target.clear();
		}
	}

	private void set(Path newPath) {
		synchronized (target) {
			target.set(newPath);
		}
	}

	private Path get() {
		synchronized (target) {
			return target.get();
		}
	}

	private boolean pathSet() {
		return get() != null;
	}

	private void handle(String string) {
		synchronized (lineProcessor) {
			lineProcessor.apply(Line.create(currentLine++, string));
		}
	}

	private void requireReadable(final Path path) throws IOException {
		if (!Files.isRegularFile(path)) {
			throw new IOException("Set path is no file");
		}
		if (!Files.isReadable(path)) {
			throw new IOException(path.toAbsolutePath().toString() + " is not readable");
		}
	}

	@Override
	public void open(String path) throws IOException {
		open(Paths.get(path));
	}

	@Override
	public void open(Path path) throws IOException {
		if (!Files.isRegularFile(path)) {
			throw new IOException("No File: " + path);
		}
		if (pathSet()) {
			throw new IOException("Already bound to " + get());
		}
		set(path);
	}

	@Override
	public void close() {
		if (pathSet()) {
			setEmpty();
		}
	}

	@Override
	public synchronized void read() throws IOException {
		if (!pathSet()) {
			throw new IOException("No set file to read from");
		}
		final Path path = get();
		requireReadable(path);
		currentLine = 0;
		synchronized (this) {
			try (Stream lines = Files.lines(path, Charset.defaultCharset())) {
				lines.forEachOrdered(this::handle);
			}
		}
	}

	@Override
	public void read(final StringBuilder stringBuilder) throws IOException {
		LocalConsumer consumer = new LocalConsumer(stringBuilder);
		processLine(consumer);
		read();
		stopProcessing(consumer);
	}

	@Override
	public void processLine(Consumer consumer) {
		synchronized (lineProcessor) {
			lineProcessor.addLast(consumer);
		}
	}

	@Override
	public void stopProcessing(Consumer consumer) {
		synchronized (lineProcessor) {
			lineProcessor.remove(consumer);
		}
	}

	private final class LocalConsumer implements Consumer {

		private final StringBuilder stringBuilder;

		public LocalConsumer(final StringBuilder stringBuilder) {

			this.stringBuilder = stringBuilder;
		}

		/**
		 * Performs this operation on the given argument.
		 *
		 * @param s the input argument
		 */
		@Override
		public void accept(Line s) {
			stringBuilder.append(s.getContent());
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy