GeometryIOUtils.java
- /*
- * 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.commons.geometry.io.core.internal;
- import java.io.BufferedReader;
- import java.io.BufferedWriter;
- import java.io.Closeable;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStreamWriter;
- import java.io.UncheckedIOException;
- import java.net.URL;
- import java.nio.charset.Charset;
- import java.nio.file.Path;
- import java.util.stream.Stream;
- import org.apache.commons.geometry.io.core.input.GeometryInput;
- import org.apache.commons.geometry.io.core.output.GeometryOutput;
- /** Internal class containing utility methods for IO operations.
- */
- public final class GeometryIOUtils {
- /** Path separator character used on Unix-like systems. */
- private static final char UNIX_PATH_SEP = '/';
- /** Path separator character used on Windows. */
- private static final char WINDOWS_PATH_SEP = '\\';
- /** Utility class; no instantiation. */
- private GeometryIOUtils() {}
- /** Get the file name of the given path or null if one does not exist
- * or is the empty string.
- * @param path path to get the file name of
- * @return file name of the given path
- */
- public static String getFileName(final Path path) {
- if (path != null) {
- return getFileName(path.toString());
- }
- return null;
- }
- /** Get the file name of the given url or null if one does not exist or is
- * the empty string.
- * @param url url to get the file name of
- * @return file name of the given url
- */
- public static String getFileName(final URL url) {
- if (url != null) {
- return getFileName(url.getPath());
- }
- return null;
- }
- /** Get the file name from the given path string, defined as
- * the substring following the last path separator character.
- * Null is returned if the argument is null or the file name is
- * the empty string.
- * @param path path to get the file name from
- * @return file name of the given path string or null if a
- * non-empty file name does not exist
- */
- public static String getFileName(final String path) {
- if (path != null) {
- final int lastSep = Math.max(
- path.lastIndexOf(UNIX_PATH_SEP),
- path.lastIndexOf(WINDOWS_PATH_SEP));
- if (lastSep < path.length() - 1) {
- return path.substring(lastSep + 1);
- }
- }
- return null;
- }
- /** Get the part of the file name after the last dot.
- * @param fileName file name to get the extension for
- * @return the extension of the file name, the empty string if no extension is found, or
- * null if the argument is null
- */
- public static String getFileExtension(final String fileName) {
- if (fileName != null) {
- final int idx = fileName.lastIndexOf('.');
- if (idx > -1) {
- return fileName.substring(idx + 1);
- }
- return "";
- }
- return null;
- }
- /** Create a {@link BufferedReader} for reading from the given input. The charset used is the charset
- * defined in {@code input} or {@code defaultCharset} if null.
- * @param input input to read from
- * @param defaultCharset charset to use if no charset is defined in the input
- * @return new reader instance
- * @throws UncheckedIOException if an I/O error occurs
- */
- public static BufferedReader createBufferedReader(final GeometryInput input, final Charset defaultCharset) {
- final Charset charset = input.getCharset() != null ?
- input.getCharset() :
- defaultCharset;
- return new BufferedReader(new InputStreamReader(input.getInputStream(), charset));
- }
- /** Create a {@link BufferedWriter} for writing to the given output. The charset used is the charset
- * defined in {@code output} or {@code defaultCharset} if null.
- * @param output output to write to
- * @param defaultCharset charset to use if no charset is defined in the output
- * @return new writer instance
- * @throws UncheckedIOException if an I/O error occurs
- */
- public static BufferedWriter createBufferedWriter(final GeometryOutput output, final Charset defaultCharset) {
- final Charset charset = output.getCharset() != null ?
- output.getCharset() :
- defaultCharset;
- return new BufferedWriter(new OutputStreamWriter(output.getOutputStream(), charset));
- }
- /** Get a value from {@code supplier}, wrapping any {@link IOException} with
- * {@link UncheckedIOException}.
- * @param <T> returned type
- * @param supplier object supplying the return value
- * @return supplied value
- * @throws UncheckedIOException if an I/O error occurs
- */
- public static <T> T getUnchecked(final IOSupplier<T> supplier) {
- try {
- return supplier.get();
- } catch (IOException exc) {
- throw createUnchecked(exc);
- }
- }
- /** Pass the given argument to the consumer, wrapping any {@link IOException} with
- * {@link UncheckedIOException}.
- * @param <T> argument type
- * @param consumer function to call
- * @param arg function argument
- * @throws UncheckedIOException if an I/O error occurs
- */
- public static <T> void acceptUnchecked(final IOConsumer<T> consumer, final T arg) {
- try {
- consumer.accept(arg);
- } catch (IOException exc) {
- throw createUnchecked(exc);
- }
- }
- /** Call the given function with the argument and return the {@code int} result, wrapping any
- * {@link IOException} with {@link UncheckedIOException}.
- * @param <T> argument type
- * @param fn function to call
- * @param arg function argument
- * @return int value
- * @throws UncheckedIOException if an I/O error occurs
- */
- public static <T> int applyAsIntUnchecked(final IOToIntFunction<T> fn, final T arg) {
- try {
- return fn.applyAsInt(arg);
- } catch (IOException exc) {
- throw createUnchecked(exc);
- }
- }
- /** Close the argument, wrapping any IO exceptions with {@link UncheckedIOException}.
- * @param closeable argument to close
- * @throws UncheckedIOException if an I/O error occurs
- */
- public static void closeUnchecked(final Closeable closeable) {
- try {
- closeable.close();
- } catch (IOException exc) {
- throw createUnchecked(exc);
- }
- }
- /** Create an unchecked exception from the given checked exception. The message of the
- * returned exception contains the original exception's type and message.
- * @param exc exception to wrap in an unchecked exception
- * @return the unchecked exception
- */
- public static UncheckedIOException createUnchecked(final IOException exc) {
- final String msg = exc.getClass().getSimpleName() + ": " + exc.getMessage();
- return new UncheckedIOException(msg, exc);
- }
- /** Create an exception indicating a parsing or syntax error.
- * @param msg exception message
- * @return an exception indicating a parsing or syntax error
- */
- public static IllegalStateException parseError(final String msg) {
- return parseError(msg, null);
- }
- /** Create an exception indicating a parsing or syntax error.
- * @param msg exception message
- * @param cause exception cause
- * @return an exception indicating a parsing or syntax error
- */
- public static IllegalStateException parseError(final String msg, final Throwable cause) {
- return new IllegalStateException(msg, cause);
- }
- /** Pass a supplied {@link Closeable} instance to {@code function} and return the result.
- * The {@code Closeable} instance returned by the supplier is closed if function execution
- * fails, otherwise the instance is <em>not</em> closed.
- * @param <T> Return type
- * @param <C> Closeable type
- * @param function function called with the supplied Closeable instance
- * @param closeableSupplier supplier used to obtain a Closeable instance
- * @return result of calling {@code function} with a supplied Closeable instance
- * @throws java.io.UncheckedIOException if an I/O error occurs
- */
- public static <T, C extends Closeable> T tryApplyCloseable(final IOFunction<C, T> function,
- final IOSupplier<? extends C> closeableSupplier) {
- C closeable = null;
- RuntimeException exc;
- try {
- closeable = closeableSupplier.get();
- return function.apply(closeable);
- } catch (RuntimeException e) {
- exc = e;
- } catch (IOException e) {
- exc = createUnchecked(e);
- }
- if (closeable != null) {
- try {
- closeable.close();
- } catch (IOException suppressed) {
- exc.addSuppressed(suppressed);
- }
- }
- throw exc;
- }
- /** Create a stream associated with an input stream. The input stream is closed when the
- * stream is closed and also closed if stream creation fails. Any {@link IOException} thrown
- * when the input stream is closed after the return of this method are wrapped with {@link UncheckedIOException}.
- * @param <T> Stream element type
- * @param <I> Input stream type
- * @param streamFunction function accepting an input stream and returning a stream
- * @param inputStreamSupplier supplier used to obtain the input stream
- * @return stream associated with the input stream return by the supplier
- * @throws java.io.UncheckedIOException if an I/O error occurs during input stream and stream creation
- */
- public static <T, I extends InputStream> Stream<T> createCloseableStream(
- final IOFunction<I, Stream<T>> streamFunction, final IOSupplier<? extends I> inputStreamSupplier) {
- return tryApplyCloseable(
- in -> streamFunction.apply(in).onClose(closeAsUncheckedRunnable(in)),
- inputStreamSupplier);
- }
- /** Return a {@link Runnable} that calls {@link Closeable#getClass() close()} on the argument,
- * wrapping any {@link IOException} with {@link UncheckedIOException}.
- * @param closeable instance to be closed
- * @return runnable that calls {@code close()) on the argument
- */
- private static Runnable closeAsUncheckedRunnable(final Closeable closeable) {
- return () -> closeUnchecked(closeable);
- }
- }