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

org.comroid.api.Disposable Maven / Gradle / Ivy

The newest version!
package org.comroid.api;

import org.jetbrains.annotations.ApiStatus.OverrideOnly;
import org.jetbrains.annotations.Nullable;

import java.io.OutputStream;
import java.io.PrintStream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public interface Disposable extends AutoCloseable {
    Collection getChildren();

    void addChildren(AutoCloseable child);

    @OverrideOnly
    @SuppressWarnings("RedundantThrows")
    default void closeContainer() throws Exception {
    }

    @Override
    default void close() throws MultipleExceptions {
        disposeThrow();
    }

    default List dispose() {
        return Collections.unmodifiableList(Stream.concat(
                Stream.of(this::closeContainer),
                getChildren().stream()
        )
                .map(closeable -> {
                    try {
                        closeable.close();
                    } catch (Exception e) {
                        return e;
                    }

                    return null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList()));
    }

    default void disposeThrow() throws MultipleExceptions {
        final List throwables = dispose();

        if (throwables.isEmpty()) {
            return;
        }

        throw new MultipleExceptions(throwables);
    }

    interface Container extends Disposable {
        Disposable getUnderlyingDisposable();

        @Override
        default Collection getChildren() {
            return getUnderlyingDisposable().getChildren();
        }

        @Override
        default void addChildren(AutoCloseable child) {
            getUnderlyingDisposable().addChildren(child);
        }
    }

    class Basic implements Disposable {
        private final List children = new ArrayList<>();

        @Override
        public List getChildren() {
            return children;
        }

        @Override
        public void addChildren(AutoCloseable child) {
            if (child == this) {
                throw new IllegalArgumentException("Disposable cannot contain itself!");
            }

            children.add(child);
        }
    }

    final class MultipleExceptions extends RuntimeException {
        public MultipleExceptions(String message, Collection causes) {
            super(composeMessage(message, causes));
        }

        public MultipleExceptions(Collection causes) {
            super(composeMessage(null, causes));
        }

        private static String composeMessage(
                @Nullable String baseMessage, Collection throwables
        ) {
            class StringStream extends OutputStream {
                private final StringBuilder sb = new StringBuilder();

                @Override
                public void write(int b) {
                    sb.append((char) b);
                }

                @Override
                public String toString() {
                    return sb.toString();
                }
            }

            if (baseMessage == null) {
                baseMessage = "Multiple Exceptions were thrown";
            }
            final StringStream out = new StringStream();
            final PrintStream string = new PrintStream(out);

            string.println(baseMessage);
            string.println("Sub Stacktraces in order:");
            throwables.forEach(t -> t.printStackTrace(string));

            return out.toString();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy