/*
 * Copyright 1996-2015 United States Government as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gsfc.nssdc.cdf;

import gsfc.nssdc.cdf.util.*;
import gsfc.nssdc.cdf.*;
import java.util.Hashtable;

/**
 * This class defines the informational, warning, and error messages that
 * can arise from CDF operations. 
 *
 * @author Phil Williams, QSS Group Inc/RITSS <BR>
 *         Mike Liu, RSTX 
 */
public class CDFException 
    extends java.lang.Exception 
    implements CDFConstants
{

    private static final Hashtable msgs;
    private long   myStatus;

    // Static initializer for msgs
    static {
	msgs = new Hashtable();

	msgs.put(Long.valueOf(ATTR_EXISTS), "Named attribute already exists.");
	msgs.put(Long.valueOf(ATTR_NAME_TRUNC), "Attribute name truncated.");
	msgs.put(Long.valueOf(BAD_ALLOCATE_RECS), "Illegal number of records "+
		 "to allocate specified.");
	msgs.put(Long.valueOf(BAD_ARGUMENT), "Illegal/undefined argument "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_ATTR_NAME), "Illegal attribute name specified.");
	msgs.put(Long.valueOf(BAD_ATTR_NUM), "Illegal attribute number "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_CACHE_SIZE), "Illegal number of cache buffers "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_CDF_EXTENSION), "Illegal/missing extension for "+
		 "multi-file CDF.");
	msgs.put(Long.valueOf(BAD_CDF_ID), "CDF identifier is unknown or "+
		 "invalid.");
	msgs.put(Long.valueOf(BAD_CDF_NAME), "Illegal CDF name specified.");
	msgs.put(Long.valueOf(BAD_CDFSTATUS), "Unknown CDF status code "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_COMPRESSION_PARM), "An illegal compression "+
		 "parameter was specified.");
	msgs.put(Long.valueOf(BAD_DATA_TYPE), "Unknown data type specified or "+
		 "encountered.");
	msgs.put(Long.valueOf(BAD_DECODING), "Unknown or unsupported data "+
		 "decoding specified.");
	msgs.put(Long.valueOf(BAD_DIM_COUNT), "Illegal dimension count "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_DIM_INDEX), "Dimension index out of range.");
	msgs.put(Long.valueOf(BAD_DIM_INTERVAL), "Illegal dimension interval "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_DIM_SIZE), "Dimension size specified as zero "+
		 "or less.");
	msgs.put(Long.valueOf(BAD_ENCODING), "Unknown or unsupported data "+
		 "encoding.");
	msgs.put(Long.valueOf(BAD_ENTRY_NUM), "Illegal attribute entry number "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_BLOCKING_FACTOR), "Illegal blocking factor "+
		 "specified (less than zero).");
	msgs.put(Long.valueOf(BAD_FNC_OR_ITEM), "The specified function or item "+
		 "is illegal.");
	msgs.put(Long.valueOf(BAD_FORMAT), "Unknown CDF format specified.");
	msgs.put(Long.valueOf(BAD_INITIAL_RECS), "Illegal number of initial "+
		 "records.");
	msgs.put(Long.valueOf(BAD_MAJORITY), "Unknown variable majority "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_MALLOC), "Unable to allocate dynamic memory.");
	msgs.put(Long.valueOf(BAD_NEGtoPOSfp0_MODE), "Illegal negative to "+
		 "positive floating point zero mode.");
	msgs.put(Long.valueOf(BAD_NUM_DIMS), "Illegal number of dimensions.");
	msgs.put(Long.valueOf(BAD_NUM_ELEMS), "Illegal number of elements "+
		 "(for data type).");
	msgs.put(Long.valueOf(BAD_NUM_VARS), "Illegal number of variables "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_READONLY_MODE), "Illegal read-only mode "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_REC_COUNT), "Illegal record count specified.");
	msgs.put(Long.valueOf(BAD_REC_INTERVAL), "Illegal record interval "+
		 "specified.");
	msgs.put(Long.valueOf(BAD_REC_NUM), "Record number is out of range.");
	msgs.put(Long.valueOf(BAD_SCOPE), "Unrecognized attribute scope.");
	msgs.put(Long.valueOf(BAD_SPARSEARRAYS_PARM), "An illegal sparse "+
		 "arrays parameter was specified.");
	msgs.put(Long.valueOf(BAD_SCRATCH_DIR), "An illegal scratch directory "+
		 "was specified.");
	msgs.put(Long.valueOf(BAD_VAR_NAME), "Illegal variable name specified.");
	msgs.put(Long.valueOf(BAD_VAR_NUM), "Illegal variable number specified.");
	msgs.put(Long.valueOf(BAD_zMODE), "Illegal zMode specified.");
	msgs.put(Long.valueOf(CANNOT_ALLOCATE_RECORDS), "Records can't be "+
		 "allocated at this time.");
	msgs.put(Long.valueOf(CANNOT_CHANGE), "The parameter/value can't be "+
		 "set/changed.");
	msgs.put(Long.valueOf(CANNOT_COMPRESS), "The compression for the "+
		 "CDF/variable can't be set/modified.");
	msgs.put(Long.valueOf(CANNOT_COPY), "The source/destination variables "+
		 "have a different dataType/numElements/numDims/dimSizes/"+
		 "dimVariances.");
	msgs.put(Long.valueOf(CANNOT_INSERT_RECORDS), "Cannot insert records to " +
		 "a variable with sparserecords..");
	msgs.put(Long.valueOf(CANNOT_SPARSEARRAYS), "Sparse arrays can't be "+
		 "set/modified for the variable.");
	msgs.put(Long.valueOf(CANNOT_SPARSERECORDS), "Sparse records can't be "+
		 "set/modified for the variable.");
	msgs.put(Long.valueOf(CDF_CLOSE_ERROR), "Close failed - error from file "+
		 "system.");
	msgs.put(Long.valueOf(CDF_CREATE_ERROR), "Creation failed - error from "+
		 "file system.");
	msgs.put(Long.valueOf(CDF_DELETE_ERROR), "Deletion failed - error from "+
		 "file system.");
	msgs.put(Long.valueOf(CDF_EXISTS), "The CDF named already exists.");
	msgs.put(Long.valueOf(CDF_INTERNAL_ERROR), "An internal error has "+
		 "occurred in the CDF library.");
	msgs.put(Long.valueOf(CDF_NAME_TRUNC), "CDF pathname truncated.");
	msgs.put(Long.valueOf(CDF_OK), "Function completed successfully.");
	msgs.put(Long.valueOf(CDF_OPEN_ERROR), "Open failed - error from file "+
		 "system.");
	msgs.put(Long.valueOf(CDF_READ_ERROR), "Read failed - error from file "+
		 "system.");
	msgs.put(Long.valueOf(CDF_WRITE_ERROR), "Write failed - error from "+
		 "file system.");
	msgs.put(Long.valueOf(CORRUPTED_V2_CDF), "Version 2 CDF is corrupted.");
	msgs.put(Long.valueOf(DATATYPE_MISMATCH), "Variable data type "+
		 "mismatch: defined vs actual");
	msgs.put(Long.valueOf(DECOMPRESSION_ERROR), "An error was detected in "+
		 "the compressed data.");
	msgs.put(Long.valueOf(DID_NOT_COMPRESS), "The CDF or variable values "+
		 "did not compress.");
	msgs.put(Long.valueOf(EMPTY_COMPRESSED_CDF), "No internal records in a "+
		 "compressed CDF.");
	msgs.put(Long.valueOf(END_OF_VAR), "Current position is at the end of "+
		 "the variable.");
	msgs.put(Long.valueOf(FORCED_PARAMETER), "A specified parameter was "+
		 "changed to a different value.");
	msgs.put(Long.valueOf(IBM_PC_OVERFLOW), "Greater than 64Kb of memory "+
		 "required.");
	msgs.put(Long.valueOf(ILLEGAL_FOR_SCOPE), "The operation is illegal "+
		 "for the attribute's scope.");
	msgs.put(Long.valueOf(ILLEGAL_IN_zMODE), "Operation is illegal while in "+
		 "zMode.");
	msgs.put(Long.valueOf(ILLEGAL_ON_V1_CDF), "Operation not allowed on "+
		 "Version 1 CDFs.");
	msgs.put(Long.valueOf(MULTI_FILE_FORMAT), "Operation n/a when multi-file "+
		 "format.");
	msgs.put(Long.valueOf(NA_FOR_VARIABLE), "Operation n/a for the type of "+
		 "variable.");
	msgs.put(Long.valueOf(NEGATIVE_FP_ZERO), "A negative floating point "+
		 "zero (-0.0) was detected.");
	msgs.put(Long.valueOf(NO_ATTR_SELECTED), "An attribute has not been "+
		 "selected.");
	msgs.put(Long.valueOf(NO_CDF_SELECTED), "A CDF has not been selected.");
	msgs.put(Long.valueOf(NO_DELETE_ACCESS), "Deleting is not allowed "+
		 "(read only).");
	msgs.put(Long.valueOf(NO_ENTRY_SELECTED), "An attribute entry has not "+
		 "been selected.");
	msgs.put(Long.valueOf(NO_MORE_ACCESS), "No more access to the CDF due "+
		 "to a severe error.");
	msgs.put(Long.valueOf(NO_PADVALUE_SPECIFIED), "A pad value has not been "+
		 "specified.");
	msgs.put(Long.valueOf(NO_STATUS_SELECTED), "A CDF status code has not "+
		 "been selected.");
	msgs.put(Long.valueOf(NO_SUCH_ATTR), "Named attribute not found in this "+
		 "CDF.");
	msgs.put(Long.valueOf(NO_SUCH_CDF), "The specified CDF does not exist.");
	msgs.put(Long.valueOf(NO_SUCH_ENTRY), "No such entry for specified "+
		 "attribute.");
	msgs.put(Long.valueOf(NO_SUCH_RECORD), "The specified record does not "+
		 "exist.");
	msgs.put(Long.valueOf(NO_SUCH_VAR), "Named variable not found in this "+
		 "CDF.");
	msgs.put(Long.valueOf(NO_VAR_SELECTED), "A variable has not been "+
		 "selected.");
	msgs.put(Long.valueOf(NO_VARS_IN_CDF), "CDF contains no rVariables.");
	msgs.put(Long.valueOf(NO_WRITE_ACCESS), "Write access is not allowed "+
		 "on the CDF file(s).");
	msgs.put(Long.valueOf(NOT_A_CDF), "Named CDF is corrupted or not "+
		 "actually a CDF.");
	msgs.put(Long.valueOf(PRECEEDING_RECORDS_ALLOCATED), "The preceeding "+
		 "records were also allocated.");
	msgs.put(Long.valueOf(READ_ONLY_DISTRIBUTION), "Writing/deleting is "+
		 "illegal.");
	msgs.put(Long.valueOf(READ_ONLY_MODE), "CDF is in read-only mode.");
	msgs.put(Long.valueOf(SCRATCH_CREATE_ERROR), "Scratch file creation "+
		 "failed - error from file system.");
	msgs.put(Long.valueOf(SCRATCH_DELETE_ERROR), "Scratch file deletion "+
		 "failed - error from file system.");
	msgs.put(Long.valueOf(SCRATCH_READ_ERROR), "Scratch file read failed - "+
		 "error from file system.");
	msgs.put(Long.valueOf(SCRATCH_WRITE_ERROR), "Scratch file write failed - "+
		 "error from file system.");
	msgs.put(Long.valueOf(SINGLE_FILE_FORMAT), "Operation n/a when "+
		 "single-file format.");
	msgs.put(Long.valueOf(SOME_ALREADY_ALLOCATED), "One or more of the "+
		 "records were already allocated.");
	msgs.put(Long.valueOf(TOO_MANY_PARMS), "Too many parameters were "+
		 "encountered.");
	msgs.put(Long.valueOf(TOO_MANY_VARS), "Only a limited number of "+
		 "variables may exist in this CDF.");
	msgs.put(Long.valueOf(TT2000_CDF_MAYNEEDUPDATE), "CDF version or its file-based template " +
		 "may need to upgrade to handle TT2000 data properly (even its TT2000 " +
                 "value may be valid).");
	msgs.put(Long.valueOf(TT2000_USED_OUTDATED_TABLE), "A TT2000 data "+
		 "is either invalid (made with an oudated leap second " +
                 "table) or trying to use an outdated table.");
	msgs.put(Long.valueOf(UNKNOWN_COMPRESSION), "An unknown type of "+
		 "compression was encountered.");
	msgs.put(Long.valueOf(UNKNOWN_SPARSENESS), "An unknown sparseness was"+
		 " encountered.");
	msgs.put(Long.valueOf(UNSUPPORTED_OPERATION), "The attempted operation "+
		 "isn't supported at this time.");
	msgs.put(Long.valueOf(VAR_ALREADY_CLOSED), "Variable is already closed.");
	msgs.put(Long.valueOf(VAR_CLOSE_ERROR), "Close failed - error from "+
		 "file system.");
	msgs.put(Long.valueOf(VAR_CREATE_ERROR), "Creation failed - error "+
		 "from file system.");
	msgs.put(Long.valueOf(VAR_DELETE_ERROR), "Deletion failed - error "+
		 "from file system.");
	msgs.put(Long.valueOf(VAR_EXISTS), "Named variable already exists.");
	msgs.put(Long.valueOf(VAR_NAME_TRUNC), "Variable name truncated.");
	msgs.put(Long.valueOf(VAR_OPEN_ERROR), "Open failed - error from "+
		 "file system.");
	msgs.put(Long.valueOf(VAR_READ_ERROR), "Read failed - error from "+
		 "file system.");
	msgs.put(Long.valueOf(VAR_WRITE_ERROR), "Write failed - error from "+
		 "file system.");
	msgs.put(Long.valueOf(VIRTUAL_RECORD_DATA), "One or more of the "+
		 "records are virtual.");
	msgs.put(Long.valueOf(NOT_A_CDF_OR_NOT_SUPPORTED), "Named CDF is "+
                 "corrupted or not supported by the current library version.");
        msgs.put(Long.valueOf(CORRUPTED_V3_CDF), "Version 3 CDF is corrupted.");
        msgs.put(Long.valueOf(ILLEGAL_EPOCH_FIELD), "One or more of the "+
                 "date/time fields is out of valid range.");
        msgs.put(Long.valueOf(CDF_SAVE_ERROR), "CDF save failed - error from " +
                 "file system.");
        msgs.put(Long.valueOf(VAR_SAVE_ERROR), "Var save failed - error from " +
                 "file system.");
        msgs.put(Long.valueOf(BAD_CHECKSUM), "The specified checksum method is not"+
                 " currently supported.");
        msgs.put(Long.valueOf(CHECKSUM_ERROR), "The data integrity verification " +
                 "through the checksum failed."); 
	msgs.put(Long.valueOf(CHECKSUM_NOT_ALLOWED), "The checksum is not allowed"+
		" for old versioned files.");
	msgs.put(Long.valueOf(IS_A_NETCDF), "Named CDF is actually a netCDF file.");
        msgs.put(Long.valueOf(TT2000_TIME_ERROR), "Error handling the date/time " +
                 "for TT2000 or a TT2000 epoch."); 
        msgs.put(Long.valueOf(UNABLE_TO_PROCESS_CDF), "One of data fields is " +
                 "invalid... Upgrade the library might fix the problem.");
        msgs.put(Long.valueOf(ZLIB_COMPRESS_ERROR), "ZLIB_ERROR: Error during " +
                 "ZLIB compression.");
        msgs.put(Long.valueOf(ZLIB_UNCOMPRESS_ERROR), "ZLIB_ERROR: Error during " +
                 "ZLIB compression.");
        msgs.put(Long.valueOf(TT2000_USED_OUTDATED_TABLE), "TT2000_USED_OUTDATED_TABLE: " +
		 "A TT2000 data is either invalid (made with an oudated leap second table) or trying to use an outdated leap second table.");
        msgs.put(Long.valueOf(BADDATE_LEAPSECOND_UPDATED), "BADDATE_LEAPSECOND_UPDATED: " +
		 "The last leap second updated date is not valid (not in the leap second table).");
        msgs.put(Long.valueOf(FUNCTION_NOT_SUPPORTED), "FUNCTION_NOT_SUPPORTED: This function " +
                 "is not supported. Likely, it is trying to access an rVariable.");
        msgs.put(Long.valueOf(BLOCKINGFACTOR_TOO_SMALL), "BLOCKINGFACTOR_TOO_SMALL: " +
                 "The blocking factor set for the compressed variable is smaller than the default. It is changed but may make data access ineffective.");
        msgs.put(Long.valueOf(BLOCKINGFACTOR_TOO_SMALL2), "BLOCKINGFACTOR_TOO_SMALL2: " +
                 "The variable's blocking factor is smaller than the default if it is compressed. The compression is set but may make data access ineffective.");
        msgs.put(Long.valueOf(BLOCKINGFACTOR_TOO_LARGE), "BLOCKINGFACTOR_TOO_LARGE: " +
                 "The intended blocking factor is too large. To avoid a "+
"temporary file(s) to be created for compression, a smaller value is assigned.");
        msgs.put(Long.valueOf(CACHESIZE_TOO_SMALL), "CACHESIZE_TOO_SMALL: " +
                 "The cache size is not changed as it is smaller than the default for a compressed CDF, which can cause a temporary file to be created.");
        msgs.put(Long.valueOf(TRY_TO_READ_NONSTRING_DATA), "TRY_TO_READ_NONSTRING_DATA: " +
                 "Wrong function as the attribute entry data is non-string.");
        msgs.put(Long.valueOf(BAD_NUM_STRINGS), "BAD_NUM_STRINGS: " +
                 "Bad number of strings (at least 1 is required).");
        msgs.put(Long.valueOf(STRING_NOT_UTF8_ENCODING), "String not in UTF8 encoding form.");
        msgs.put(Long.valueOf(CANNOT_CONVERT_WIDECHAR), " Can not convert between "+
                 "wide-character string and multi-byte character string. Locale might not be properly set.");
    }

    /**
     * Takes a text message from the calling program and throws a
     * CDFException.
     *
     * @param message the message to be thrown with CDFException 
     */
    public CDFException(String message) {
	super(message);
    }

    /**
     * Takes a status code and throws a CDFException with the message
     * that corresponds to the status code that is passed in. 
     * 
     * @param statusCode the CDF statusCode to be thrown 
     */
    public CDFException(long statusCode) {
	this(statusCode, null);
    }

    /**
     * Takes a status code and throws a CDFException with the message
     * that corresponds to the status code that is passed in.
     * It also specifies where (which routine) the problem was. 
     *
     * @param statusCode the CDF statusCode to be thrown <P>
     * @param where the place (routine/method) where the problem occurred 
     *
     */
    public CDFException(long statusCode, String where) {
	super(CDFException.getStatusMsg(statusCode) +
	      (where == null ? "" : "\n  "+where));
	myStatus = statusCode;
    }

    /**
     * Gets the status code that caused CDFException.  This method comes in
     * handy when there are times one may want to examine the cause of 
     * the CDFException and determine whether to continue or not. 
     * <PRE>
     *    try {
     *         ...
     *
     *    } catch (CDFException e) {
     *          if (e.getCurrentStatus() == NO_SUCH_VAR) {
     *              Variable latitude = Variable.create(cdf, "Latitude",
     *                                                  CDF_INT1,
     *                                                  numElements,
     *                                                  numDims,
     *                                                  dimSizes,
     *                                                  recVary,
     *                                                  dimVary);
     *              ... 
     *          }
     *          else {
     *             System.out.println ("StatusCode = "+e.getCurrentStatus());
     *             e.printStackTrace();
     *          }
     *    }
     * </PRE>
     * @return the status code that caused CDFException
     */
    public long getCurrentStatus() {
	if (myStatus == 0)  // CDFException called with a method.
	    return -1;
	else
	    return myStatus;
    }

    /**
     * Get the status text message for the given status code.
     *
     * @param statusCode the status code from which the status text is 
     *                   retrieved <P>
     *
     * @return the status text message for the given status code 
     */
    public static String getStatusMsg(long statusCode) {
        return (String) msgs.get(Long.valueOf(statusCode));
    }

}
