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 &hellip;) 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 *  &hellip;), 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 &hellip;</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 */