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

com.nfbsoftware.exception.NfbCheckedException Maven / Gradle / Ivy

package com.nfbsoftware.exception;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

import com.nfbsoftware.util.Severity;
import com.nfbsoftware.util.StringUtil;

/**
 * The single checked exception class. All checked exceptions encountered within the NFB Software Core must be
 * propagated as a CheckedException.
 *
 * @author Brendan Clemenzi 
 * @email [email protected]
 */
public abstract class NfbCheckedException extends Exception
{
    /**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/**
     * The MessageFormat used by the toString method.
     */
    protected static final String TO_STRING_MESSAGE_FORMAT = "[{0} - {1} - {2} - {3}]";

    /**
     * Contains all of the codes defined by class in the checkedException class hierarchy
     */
    private static final Map CODE_MAP = new HashMap<>(31);

    /**
     * The error code of this exception class.
     */
    protected Code mCode;

    /**
     * The argument array that holds each of the arguments associated with this exception.
     */
    protected Serializable[] mArgs;

    /**
     * Debug information related to this exception class. This is typically set to the class and method name (e.g. Foo.bar).
     */
    protected String mDebugInformation;

    /**
     * The root cause of this exception class.
     */
    protected Throwable mRootCause;

    /**
     * The severity of this exception class.
     */
    protected int mSeverity;

    /**
     * The stack trace of this exception class as a String.
     */
    protected String mStackTraceString;

    /**
     * Represents a checkedException code. This class is used to
     * enforce the practice of using a code defined for an exception class.
     * Instances of the exception cannot be constructed without providing a valid
     * code. Subclasses of this class must implement a subclass of this protected
     * class. Typically, subclass constructors will take this Code
     * subclass in an internal Codes interface.
     *
     * @author Brendan Clemenzi
     */
    protected static abstract class Code implements Serializable
    {
        /**
		 *
		 */
		private static final long serialVersionUID = 1L;

		/** The mapped code value */
        private Code mMappedCode;

        /** The code value */
        private String mCode;

        /** The default message */
        private String mMessage;

        /** The code severity */
        private int mSeverity;

        /**
         * The protected constructor ensures that no instances of this class are
         * constructed outside of the exception class or its children.
         *
         * @param code the code
         * @param mappedCode the top-level code that this code should map to
         * @param message the default message
         * @param severity the severity
         */
        protected Code(String code, Code mappedCode, String message, int severity)
        {
            mCode = code;
            mMappedCode = mappedCode;
            mMessage = message;
            mSeverity = severity;
        }

        /**
         * Returns the code's value
         *
         * @return the code's value
         */
        public String getCode()
        {
            return mCode;
        }

        /**
         * Returns the code's mapped code
         *
         * @return the code's mapped code value
         */
        public Code getMappedCode()
        {
            return mMappedCode;
        }

        /**
         * Returns the code's default message.
         *
         * @return the code's default message
         */
        public String getMessage()
        {
            return mMessage;
        }

        /**
         * Returns the code's severity
         *
         * @return the code's severity
         */
        public int getSeverity()
        {
            return mSeverity;
        }

        /**
         * Returns the Code's value as a String.
         *
         * @return the code's value
         *
         * @see java.lang.Object#toString()
         */
        @Override
		public String toString()
        {
            return mCode;
        }
    }

    /**
     *
     * @see java.lang.Object#Object()
     */
    public NfbCheckedException()
    {
    }

    /**
     * Constructs an MediaMateCheckedException instance with the specified code, args, debugInformation and severity.
     *
     * @param code              the exception code
     * @param args              an argument array
     * @param debugInformation  debug information
     * @param rootCause         the root cause
     * @param severity          the severity (based upon the constants defined in the util.Severity class)
     */
    public NfbCheckedException(Code code, Object[] args, String debugInformation, Throwable rootCause, int severity)
    {
        mCode             = code;
        mDebugInformation = debugInformation;
        mRootCause        = rootCause;
        mSeverity         = severity;

        if (args != null)
        {
            int length = args.length;

            mArgs = new Serializable[length];

            for (int i = 0; i < length; i++)
            {
                Object arg = args[i];
                if (arg != null)
                {
                    if (arg instanceof Serializable)
                    {
                        mArgs[i] = (Serializable)arg;
                    }
                    else
                    {
                        mArgs[i] = arg.toString();
                    }
                }
            }
        }
        else
        {
            mArgs = new Serializable[] {};
        }
    }

    /**
     * Gets the default Code.
     *
     * @return the default code
     */
    protected abstract Code getDefaultCode();

    /**
     * Gets the exception code
     *
     * @return the exception code
     */
    public Code getCode()
    {
        return mCode;
    }

    /**
     * Gets the exception code name (aka the error code).
     *
     * @return the code name
     */
    public String getCodeName()
    {
        return mCode.getCode();
    }

    /**
     * Gets the argument array associated with the exception code.
     *
     * @return the arguement array.
     */
    public Serializable[] getArgs()
    {
        return mArgs;
    }

    /**
     * Gets the debug information.
     *
     * @return the debug information.
     */
    public String getDebugInformation()
    {
        return mDebugInformation;
    }

    /**
     * Gets the severity.
     *
     * @return the severity.
     */
    public Throwable getRootCause()
    {
        return mRootCause;
    }

    /**
     * Gets the severity.
     *
     * @return the severity.
     */
    public int getSeverity()
    {
        return mSeverity;
    }

    /**
     * Gets the severity as a String. Returns one of the following:
     * 
    *
  • FATAL *
  • ERROR *
  • WARNING *
  • INFO *
  • SUCCESS *
  • DEBUG *
* * @return the severity as a String. */ public String getSeverityAsString() { switch (mSeverity) { case Severity.FATAL: return "FATAL"; case Severity.ERROR: return "ERROR"; case Severity.WARNING: return "WARNING"; case Severity.INFORMATIONAL: return "INFO"; case Severity.SUCCESS: return "SUCCESS"; case Severity.DEBUG: return "DEBUG"; default: return "ERROR"; } } /** * Returns the message based upon the error code and arguments provided * to this class as part of the constructor. * * @return the message. */ @Override public String getMessage() { String result = MessageFormat.format(mCode.getMessage().trim(), getArgs()).trim(); return result; } /** Returns true if severity of this exception is ERROR or FATAL. Returns false otherwise. * * @return true if the severity of this exception is ERROR or FATAL; false otherwise. */ public boolean isSevere() { return mSeverity <= Severity.ERROR; } /** * Saves the stack trace (as a String) of this exception class. This is done so that the stack trace is serialized for any * and all server-side exceptions. * *

Note, the stack trace of the root cause is saved in the event that this exception wraps a root cause. */ private String buildStackTrace() { StringBuffer results = new StringBuffer(buildStackTrace(this)); for (Throwable rootCause = mRootCause; rootCause != null;) { results.append("Caused by: "); if (rootCause instanceof NfbCheckedException) { results.append(buildStackTrace(rootCause)); rootCause = ((NfbCheckedException)rootCause).getRootCause(); } else if (rootCause instanceof NfbRuntimeException) { results.append(buildStackTrace(rootCause)); rootCause = ((NfbRuntimeException)rootCause).getRootCause(); } else { results.append(buildStackTrace(rootCause)); rootCause = null; } } return results.toString(); } /** * Returns the stack trace (as a String) of the specified Throwable. Removes the results of the exception toString() method * from the stack trace string prior to returning. * * @param t the Throwable. * @return the stack trace (as a String) of the specified Throwable. */ private String buildStackTrace(Throwable t) { StringWriter writer = new StringWriter(); t.printStackTrace(new PrintWriter(writer)); String s = writer.toString(); if (t == this) { // Parse the exception toString results from the stack trace string. int i = s.indexOf("\n\tat "); if (i != -1) { String stackTraceString = s.substring(i); return stackTraceString; } return StringUtil.EMPTY_STRING; } return s; } /** * Gets the stack trace (as a String) of this object if the exception severity is ERROR or FATAL. Returns the empty string * if the exception severity is not ERROR or FATAL. * *

* Note, the the stack trace of this object will be the stack trace of the root cause if the exception severity is ERROR or * FATAL and this object wraps a root cause. * *

* Note, the results of the exception toString method are removed from the stack trace string prior to it being returned to * the caller. * * @return the stack trace (as a String) of this object. */ public String getStackTraceString() { if (mStackTraceString == null) { mStackTraceString = buildStackTrace(); } return mStackTraceString; } /** * Returns a String representation of this object. e.g. *

     *     [ERROR - 2002 - ContractTypeDao.find
     *     No records found in table: CONTRACTS]
     * 
* * @return a String representation of this object. */ @Override public String toString() { Object[] args = new Object[] { getSeverityAsString(), mCode, mDebugInformation, getMessage()}; return MessageFormat.format(TO_STRING_MESSAGE_FORMAT, args); } /** * Gets the MediaMateCheckedException.Code object with the corresponding * code name. This method returns any codes defined within its subclasses, * who register their codes with this class at initialization. * * @param codeName the name of the code to retrieve * * @return the code matching the name, may be null */ public static Code getCode(String codeName) { synchronized (CODE_MAP) { return CODE_MAP.get(codeName); } } /** * Registers a code object in the code map. If a code with an identical * code name already exists, a runtime exception is thrown. * * @param code the code to register */ protected static void registerCode(Code code) { synchronized (CODE_MAP) { String codeName = code.getCode(); if (CODE_MAP.containsKey(codeName)) { // throw exception } else { CODE_MAP.put(codeName, code); } } } /** * Called when the exception is deserialized. This implementation performs * deserializaion using the standard deserialization tools, then calls autoLog(). * * @param in the stream containing the exception details * * @throws IOException thrown if an error occurs while reading the stream * @throws ClassNotFoundException thrown if a class in the stream isn't found */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy