function CWError( name, message )
{
    this.name    = name;
    this.message = this.name + ": " + ( message ? message : '' );
}
CWError.prototype = {
    Nest: function( error )
    {
        this.message += '\n<NESTED>';

        var err = (error === undefined) ? 'UNDEFINED_EXCEPTION!' : error;

        this.message += err.name ? err.name : err;
        this.message += ": ";
        this.message += err.message ? err.message : '';

        this.message += err.number ? '\nNumber: ' + err.number : '';
        this.message += err.description ? '\nDescription: ' + err.description : '';
        this.message += err.fileName ? '\nFile: ' + err.fileName : '';
        this.message += err.lineNumber ? '\nLine: ' + err.lineNumber : '';
        this.message += err.stack ? '\nStack:\n' + err.stack : '';

        this.message.replace( /\n/, '\t\n' ); /* TODO - I think this is a no-op because replace is non-descructive, right? - IKS */
    }
};

function EX_ASSERT_NO_EXCEPTIONS( error, message )
{
    var theError = new CWError( 'Unhandled exception', message );
    theError.Nest( error );
    throw theError;
}

// override this to do something useful
function EX_Log( message )
{
}

function TYPE_EX_FailedParsingCarrier( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingCarrier' ) );
    this.Nest( nestedException );
}

function TYPE_EX_FailedParsingCarrierList( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingCarrierList' ) );
    this.Nest( nestedException );
}

function TYPE_EX_FailedParsingForwardCodeList( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingForwardCodeList' ) );
    this.Nest( nestedException );
}


function TYPE_EX_FailedParsingForwardCode( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingForwardCode' ) );
    this.Nest( nestedException );
}

function TYPE_EX_FailedParsingForwardCode( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingForwardCode' ) );
    this.Nest( nestedException );
}

function TYPE_EX_FailedParsingImageClickURLPair( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingImageClickURLPair' ) );
    this.Nest( nestedException );
}

function TYPE_EX_FailedParsingCRMContent( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingCRMContent' ) );
    this.Nest( nestedException );
}

function TYPE_EX_FailedParsingEventPop( nestedException )
{
    EXT_extend( this, new CWError( 'TYPE_EX_FailedParsingEventPop' ) );
    this.Nest( nestedException );
}

function EX_ProgrammingError( message )
{
    EXT_extend( this, new CWError( 'EX_ProgrammingError', message ) );
}

function CLS_EX_InvalidClassSpecification( message )
{
    EXT_extend( this, new CWError( "CLS_EX_InvalidClassSpecification", message ) );
}

function CLS_EX_ClassAlreadyDefined( message )
{
    EXT_extend( this, new CWError( "CLS_EX_InvalidClassSpecification", message ) );
}

function CLS_EX_CannotConstructAbstractClass( className )
{
    EXT_extend( this, new CWError( "CLS_EX_CannotConstructAbstractClass", "Cannot construct object from abstract class [" + className + "]" ) );
}

function CLS_EX_InvalidCast( className, baseClassName )
{
    EXT_extend( this, new CWError( "CLS_EX_InvalidCast", "Cannot cast a [" + className + "] to a [" + baseClassName  + "]" ) );
}

function TS_EX_TimeoutServerShutdown( className, baseClassName )
{
    EXT_extend( this, new CWError( "TS_EX_TimeoutServerShutdown", "Timeout server is shutting down." ) );
}
