SafeException.java
package com.guinetik.corefun;
/**
* A runtime exception wrapper for checked exceptions.
* <p>
* {@code SafeException} provides a way to wrap checked exceptions as unchecked
* exceptions, enabling cleaner functional code without excessive try-catch blocks.
* It is the standard exception type thrown by the CoreFun library when operations fail.
* </p>
*
* <h2>Design Philosophy</h2>
* <p>
* Java's checked exceptions force explicit handling at every call site, which
* conflicts with functional programming patterns like streams and lambdas.
* {@code SafeException} bridges this gap by allowing checked exceptions to propagate
* as unchecked exceptions while preserving the original cause for debugging.
* </p>
*
* <h2>When to Use</h2>
* <ul>
* <li>Wrapping checked exceptions in lambda expressions</li>
* <li>Converting library exceptions to application-level exceptions</li>
* <li>Providing context messages while preserving the original cause</li>
* </ul>
*
* <h2>Example Usage</h2>
* <pre class="language-java"><code>
* // Manual wrapping with context
* try {
* riskyOperation();
* } catch (IOException e) {
* throw new SafeException("Failed to read file: " + path, e);
* }
*
* // Using the static wrap method (preserves RuntimeExceptions)
* try {
* operation();
* } catch (Exception e) {
* throw SafeException.wrap(e); // Returns original if already RuntimeException
* }
*
* // Adding context to any exception
* throw SafeException.wrap("Database query failed", e);
* </code></pre>
*
* @author Guinetik <guinetik@gmail.com>
* @since 0.1.0
* @see SafeRunnable
* @see SafeCallable
* @see SafeExecutor
*/
public class SafeException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* Creates a SafeException wrapping the given cause.
*
* @param cause the underlying exception
*/
public SafeException(Throwable cause) {
super(cause);
}
/**
* Creates a SafeException with a message and cause.
*
* @param message descriptive message about the error context
* @param cause the underlying exception
*/
public SafeException(String message, Throwable cause) {
super(message, cause);
}
/**
* Creates a SafeException with just a message.
*
* @param message descriptive message about the error
*/
public SafeException(String message) {
super(message);
}
/**
* Wraps a checked exception as a SafeException.
* If the exception is already a RuntimeException, it is returned as-is.
*
* @param e the exception to wrap
* @return a RuntimeException (either the original or wrapped)
*/
public static RuntimeException wrap(Exception e) {
if (e instanceof RuntimeException) {
return (RuntimeException) e;
}
return new SafeException(e);
}
/**
* Wraps a checked exception with a descriptive message.
*
* @param message context description
* @param e the exception to wrap
* @return a SafeException wrapping the original
*/
public static SafeException wrap(String message, Exception e) {
return new SafeException(message, e);
}
}