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 org.apiguardian.api.API; 021import org.tquadrat.foundation.annotation.ClassVersion; 022 023import java.io.Serial; 024 025import static java.lang.String.format; 026import static org.apiguardian.api.API.Status.STABLE; 027import static org.tquadrat.foundation.lang.Objects.nonNull; 028import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 029 030/** 031 * <p>{@summary This implementation of 032 * {@link Error} 033 * should be thrown in all cases where an unexpected exception was caught.} 034 * Unlike an 035 * {@link ImpossibleExceptionError}, 036 * the exception is <i>possible</i>, but not expected – probably because the 037 * programmer has taken (at least thought to have …) appropriate 038 * precautions against its occurrence. An example for this could be an 039 * implementation of 040 * {@link Object#clone() clone()} 041 * for a particular class: with implementing that method (and declaring the 042 * interface 043 * {@link Cloneable} 044 * …), instances of that class do support cloning and therefore that 045 * exception should not be thrown. Unfortunately, changes somewhere else in 046 * the source might prevent one of the attributes of the respective class from 047 * being cloned, so that exception could be thrown again …</p> 048 * <p>Another example could be this code sequence: 049 * <div class="source-container"><pre>… 050 * final var file = new File( … ); 051 * if( file.exists() ) 052 * { 053 * try( final var inputStream = new FileInputStream( file ) ) 054 * { 055 * … 056 * } 057 * catch( final FileNotFoundException e ) 058 * { 059 * throw new UnexpectedExceptionError( e ); 060 * } 061 * }</pre></div> 062 * <p>Although the code checked that the file exists, it could have vanished 063 * <i>unexpectedly</i> just before it was opened.</p> 064 * 065 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 066 * @version $Id: UnexpectedExceptionError.java 1163 2026-03-20 15:28:33Z tquadrat $ 067 * @since 0.0.5 068 * 069 * @UMLGraph.link 070 */ 071@ClassVersion( sourceVersion = "$Id: UnexpectedExceptionError.java 1163 2026-03-20 15:28:33Z tquadrat $" ) 072@API( status = STABLE, since = "0.0.5" ) 073public sealed class UnexpectedExceptionError extends AssertionError 074 permits ImpossibleExceptionError 075{ 076 /*-----------*\ 077 ====** Constants **======================================================== 078 \*-----------*/ 079 /** 080 * The message for this exception. 081 */ 082 private static final String MSG_UnexpectedException = "The Exception '%1$s' was not expected to occur in this context"; 083 084 /*------------------------*\ 085 ====** Static Initialisations **=========================================== 086 \*------------------------*/ 087 /** 088 * The serial version UID for objects of this class: {@value}. 089 * 090 * @hidden 091 */ 092 @Serial 093 private static final long serialVersionUID = 2233464685783981770L; 094 095 /*--------------*\ 096 ====** Constructors **===================================================== 097 \*--------------*/ 098 /** 099 * Creates a new instance of the Error. The message is a constant, only 100 * the causing exception can be given. 101 * 102 * @param cause The causing exception. 103 */ 104 public UnexpectedExceptionError( final Throwable cause ) 105 { 106 super( format( MSG_UnexpectedException, requireNonNullArgument( cause, "cause" ).getClass().getName() ) , cause ); 107 } // UnexpectedExceptionError() 108 109 /** 110 * Creates a new instance of the Error. This constructor should be used in 111 * cases where an enhanced message is useful or necessary. 112 * 113 * @param message The message for the error. 114 * @param cause The causing exception. 115 */ 116 public UnexpectedExceptionError( final String message, final Throwable cause ) 117 { 118 super( nonNull( message ) && !message.isEmpty() ? message : format( MSG_UnexpectedException, requireNonNullArgument( cause, "cause" ).getClass().getName() ), requireNonNullArgument( cause, "cause" ) ); 119 } // UnexpectedExceptionError() 120} 121// class UnexpectedExceptionError 122 123/* 124 * End of File 125 */