001/* 002 * ============================================================================ 003 * Copyright © 2002-2026 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * Licensed to the public under the agreements of the GNU Lesser General Public 007 * License, version 3.0 (the "License"). You may obtain a copy of the License at 008 * 009 * http://www.gnu.org/licenses/lgpl.html 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package org.tquadrat.foundation.exception; 019 020import static java.lang.String.format; 021import static org.apiguardian.api.API.Status.STABLE; 022import static org.tquadrat.foundation.lang.Objects.nonNull; 023import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 024 025import java.io.Serial; 026 027import org.apiguardian.api.API; 028import org.tquadrat.foundation.annotation.ClassVersion; 029 030/** 031 * <p>{@summary This implementation of 032 * {@link Error} 033 * should be thrown in all cases where an <i>unlikely</i> exception was 034 * caught.} 035 * Different from an 036 * {@link ImpossibleExceptionError}, 037 * the exception is <i>possible</i>, but <i>unlikely</i> – probably because 038 * the programmer has taken (at least thought to have …) appropriate 039 * precautions against its occurrence. An example for this could be an 040 * implementation of 041 * {@link Object#clone() clone()} 042 * for a particular class: with implementing that method (and declaring the 043 * interface 044 * {@link Cloneable} 045 * …), instances of that class do support cloning and therefore that 046 * exception should not be thrown. Unfortunately, changes somewhere else in 047 * the source might prevent one of the attributes of the respective class from 048 * being cloned, so that exception could be thrown again …</p> 049 * <p>Another example could be this code sequence: 050 * <div class="source-container"><pre>… 051 * final var file = new File( … ); 052 * if( file.exists() ) 053 * { 054 * try( final var inputStream = new FileInputStream( file ) ) 055 * { 056 * … 057 * } 058 * catch( final FileNotFoundException e ) 059 * { 060 * throw new UnexpectedExceptionError( e ); 061 * } 062 * }</pre></div> 063 * <p>Although the code checked that the file exists, it could have vanished 064 * just before it was opened.</p> 065 * <p>Previously, this error was named {@code UnexpectedExceptionError}, but 066 * the current name apparently fits better with the intention.</p> 067 * 068 * @author Thomas Thrien - thomas.thrien@tquadrat.org 069 * @version $Id: UnexpectedExceptionError.java 1293 2026-10-16 13:12:15Z tquadrat $ 070 * @since 0.25.15 071 * 072 * @UMLGraph.link 073 */ 074@ClassVersion( sourceVersion = "$Id: UnexpectedExceptionError.java 1293 2026-10-16 13:12:15Z tquadrat $" ) 075@API( status = STABLE, since = "0.0.5" ) 076public sealed class UnlikelyExceptionError extends AssertionError 077 permits ImpossibleExceptionError 078{ 079 /*-----------*\ 080 ====** Constants **======================================================== 081 \*-----------*/ 082 /** 083 * The message for this exception. 084 */ 085 private static final String MSG_UnexpectedException = "The Exception '%1$s' was not expected to occur in this context"; 086 087 /*------------------------*\ 088 ====** Static Initialisations **=========================================== 089 \*------------------------*/ 090 /** 091 * The serial version UID for objects of this class: {@value}. 092 * 093 * @hidden 094 */ 095 @Serial 096 private static final long serialVersionUID = 2233464685783981770L; 097 098 /*--------------*\ 099 ====** Constructors **===================================================== 100 \*--------------*/ 101 /** 102 * <p>{@summary {@constructor}} The message is a constant, only 103 * the causing exception can be given.</p> 104 * 105 * @param cause The causing exception. 106 */ 107 public UnlikelyExceptionError( final Throwable cause ) 108 { 109 super( format( MSG_UnexpectedException, requireNonNullArgument( cause, "cause" ).getClass().getName() ) , cause ); 110 } // UnexpectedExceptionError() 111 112 /** 113 * <p>{@summary {@constructor}} This constructor should be used in 114 * cases where an enhanced message is useful or necessary.</p> 115 * 116 * @param message The message for the error. 117 * @param cause The causing exception. 118 */ 119 public UnlikelyExceptionError( final String message, final Throwable cause ) 120 { 121 super( nonNull( message ) && !message.isEmpty() ? message : format( MSG_UnexpectedException, requireNonNullArgument( cause, "cause" ).getClass().getName() ), requireNonNullArgument( cause, "cause" ) ); 122 } // UnexpectedExceptionError() 123} 124// class UnexpectedExceptionError 125 126/* 127 * End of File 128 */