package org.dbxml.core;

/*
 * dbXML License, Version 1.0
 *
 *
 * Copyright (c) 1999-2001 The dbXML Group, L.L.C.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by
 *        The dbXML Group (http://www.dbxml.com/)."
 *    Alternately, this acknowledgment may appear in the software
 *    itself, if and wherever such third-party acknowledgments normally
 *    appear.
 *
 * 4. The names "dbXML" and "The dbXML Group" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    info@dbxml.com.
 *
 * 5. Products derived from this software may not be called "dbXML",
 *    nor may "dbXML" appear in their name, without prior written
 *    permission of The dbXML Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE DBXML GROUP OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: FaultCodes.java,v 1.25 2001/09/04 11:13:33 kstaken Exp $
 */

import java.util.*;
import org.dbxml.core.corba.db.*;
import org.dbxml.server.*;

import org.xmldb.api.base.*;

/**
 * FaultCodes defines the dbXML specific fault codes and associated error
 * messages.
 */

public abstract class FaultCodes implements org.dbxml.core.corba.db.FaultCodes {
   private static final Map FaultMsg = new HashMap();

   private FaultCodes() {}

   static {
      // General errors 0 series
      putCodeMessage(GEN_UNKNOWN, "Unknown");
      putCodeMessage(GEN_GENERAL_ERROR, "General Error");
      putCodeMessage(GEN_CRITICAL_ERROR, "Critical Error");
      putCodeMessage(GEN_FATAL_ERROR, "Fatal Error");

      // XMLObject invocation errors 100 series
      putCodeMessage(OBJ_OBJECT_NOT_FOUND, "XMLObject Not Found");
      putCodeMessage(OBJ_METHOD_NOT_FOUND, "XMLObject Method Not Found");
      putCodeMessage(OBJ_NULL_RESULT, "XMLObject Null Result");
      putCodeMessage(OBJ_INVALID_RESULT, "XMLObject Invalid Result");
      putCodeMessage(OBJ_DUPLICATE_OBJECT, "XMLObject Duplicate Object");
      putCodeMessage(OBJ_RUNTIME_EXCEPTION, "XMLObject Runtime Exception");
      putCodeMessage(OBJ_CLASS_FORMAT_ERROR, "XMLObject Class Format Error");
      putCodeMessage(OBJ_INVALID_CONTEXT, "XMLObject Invalid Context");
      putCodeMessage(OBJ_CANNOT_CREATE, "XMLObject Cannot Create");
      
      // Collection-related errors 200 series
      putCodeMessage(COL_COLLECTION_NOT_FOUND, "Collection Not Found");
      putCodeMessage(COL_DOCUMENT_NOT_FOUND, "Collection Document Not Found");
      putCodeMessage(COL_DUPLICATE_COLLECTION, "Collection Duplicated");
      putCodeMessage(COL_NULL_RESULT, "Collection Null Result");
      putCodeMessage(COL_NO_FILER, "Collection No Filer");
      putCodeMessage(COL_NO_INDEXMANAGER, "Collection No IndexManager");
      putCodeMessage(COL_DOCUMENT_MALFORMED, "Collection Document Malformed");
      putCodeMessage(COL_CANNOT_STORE, "Collection Cannot Store");
      putCodeMessage(COL_CANNOT_RETRIEVE, "Collection Cannot Retrieve");
      putCodeMessage(COL_COLLECTION_READ_ONLY, "Collection Read-only");
      putCodeMessage(COL_COLLECTION_CLOSED, "Collection Closed");
      putCodeMessage(COL_CANNOT_CREATE, "Collection Cannot Create");
      putCodeMessage(COL_CANNOT_DROP, "Collection Cannot Drop");

      // Index-related errors 300 series
      putCodeMessage(IDX_VALUE_NOT_FOUND, "Index Value Not Found");
      putCodeMessage(IDX_INDEX_NOT_FOUND, "Index Not Found");
      putCodeMessage(IDX_MATCHES_NOT_FOUND, "Index Matches Not Found");
      putCodeMessage(IDX_DUPLICATE_INDEX, "Index Duplicate Index");
      putCodeMessage(IDX_NOT_SUPPORTED, "Index Not Supported");
      putCodeMessage(IDX_STYLE_NOT_FOUND, "Index Style Not Found");
      putCodeMessage(IDX_CORRUPTED, "Index Corrupted");
      putCodeMessage(IDX_CANNOT_CREATE, "Index Cannot Create");

      // Transaction-related errors 400 series
      putCodeMessage(TRX_DOC_LOCKED, "Transaction Document Locked");
      putCodeMessage(TRX_NO_CONTEXT, "Transaction No Context");
      putCodeMessage(TRX_NOT_ACTIVE, "Transaction Not Active");
      putCodeMessage(TRX_NOT_SUPPORTED, "Transaction Not Supported");

      // Database-related errors 500 series
      putCodeMessage(DBE_NO_PARENT, "Database No Parent");
      putCodeMessage(DBE_CANNOT_DROP, "Database Cannot Drop");

      // Query-related errors 600 series
      putCodeMessage(QRY_NULL_RESULT, "Query Null Result");
      putCodeMessage(QRY_COMPILATION_ERROR, "Query Compilation Error");
      putCodeMessage(QRY_PROCESSING_ERROR, "Query Processing Error");
      putCodeMessage(QRY_NOT_SUPPORTED, "Query Not Supported");
      putCodeMessage(QRY_STYLE_NOT_FOUND, "Query Style Not Found");

      // Security-related errors 700 series
      putCodeMessage(SEC_INVALID_USER, "Security Invalid User");
      putCodeMessage(SEC_INVALID_GROUP, "Security Invalid Group");
      putCodeMessage(SEC_INVALID_ACCESS, "Security Invalid Access");
      putCodeMessage(SEC_INVALID_CREDENTIALS, "Security Invalid Credentials");
      
      // URI-related errors 800 series
      putCodeMessage(URI_EMPTY, "URI Empty");
      putCodeMessage(URI_NULL, "URI Null");
      putCodeMessage(URI_PARSE_ERROR, "URI Parse Error");
      
      // Java-related errors 2000 series
      putCodeMessage(JAVA_RUNTIME_ERROR, "Java Runtime Error");
   }

   private static void putCodeMessage(int code, String message) {
      FaultMsg.put(new Integer(code), message);
   }

   /**
    * getMessage returns a textual form for the specified fault code.
    *
    * @param code The Fault Code
    * @return It's textual form
    */
   public static String getMessage(int code) {
      String msg = (String)FaultMsg.get(new Integer(code));
      return msg != null ? msg
                         : "";
   }

   /**
    * createAPIException creates an APIException instance based
    * on the specified parameters.
    *
    * @param code The Fault Code
    * @return An APIException instance
    */
   public static APIException createAPIException(int code) {
      return new APIException(code, getMessage(code), "");
   }

   /**
    * createAPIException creates an APIException instance based
    * on the specified parameters.
    *
    * @param code The Fault Code
    * @param message A specific message to associate
    * @return An APIException instance
    */
   public static APIException createAPIException(int code, String message) {
      return new APIException(code, getMessage(code), message);
   }

   /**
    * createAPIException creates an APIException instance based
    * on the specified Exception.  If the Exception is a DBException,
    * it will extract any important information from it (like fault
    * codes and messages)
    *
    * @param e The Exception to use
    * @return An APIException instance
    */
   public static APIException createAPIException(Exception e) {
      if ( e instanceof APIException )
         return (APIException)e;
      else {
         String m = e.getMessage();
         if ( m == null )
            m = "";

         if ( e instanceof RuntimeException )
            return new APIException(JAVA_RUNTIME_ERROR, getMessage(JAVA_RUNTIME_ERROR), m);
         else if ( e instanceof DBException ) {
            DBException d = (DBException)e;
            return new APIException(d.faultCode, getMessage(d.faultCode), m);
         }
         else
            return new APIException(GEN_UNKNOWN, getMessage(GEN_UNKNOWN), m);
      }
   }

   /**
    * createXMLDBException creates an XMLDBException instance based
    * on the specified Exception.  If the Exception is a DBException,
    * it will extract any important information from it (like fault
    * codes and messages)
    *
    * @param e The Exception to use
    * @return An XMLDBException instance
    */
   public static XMLDBException createXMLDBException(Exception e) {
      if ( e instanceof XMLDBException )
         return (XMLDBException)e;
      else if ( e instanceof DBException ) {
         DBException d = (DBException)e;
         return new XMLDBException(ErrorCodes.VENDOR_ERROR, d.faultCode, getMessage(d.faultCode));
      }
      else if ( e instanceof APIException ) {
         APIException a = (APIException)e;
         return new XMLDBException(ErrorCodes.VENDOR_ERROR, a.faultCode, a.faultMessage);
      }
      else {
         String m = e.getMessage();
         if ( m == null )
            m = "";
         int code = e instanceof RuntimeException ? JAVA_RUNTIME_ERROR
                                                  : GEN_UNKNOWN;
         return new XMLDBException(ErrorCodes.VENDOR_ERROR, code, m);
      }
   }

   /**
    * getFaultCodeType examines the provided exception to determine
    * the general fault code that is associated with it.  General
    * fault codes are reduced from actual fault codes to be one of
    * the GEN_ prefixed fault code values.
    *
    * @param e The Exception to examine
    * @return The General Fault Code
    */
   public static int getFaultCodeType(Exception e) {
      int code = 0;
      if ( e instanceof DBException )
         code = ((DBException)e).faultCode;
      else if ( e instanceof APIException )
         code = ((APIException)e).faultCode;
      // Strip it to the General series
      code = code % 100;
      // Narrow to a General value
      code = code - ( code % 10 );
      return code;
   }

   /**
    * getFaultCodeSeries examines the provided exception to
    * determine the fault code series that is associated with it.
    * Series are reduced from actual fault codes to be one of
    * the fault code prefixes (ex: COL, DB, SEC).
    *
    * @param e The Exception to examine
    * @return The Fault Code Series
    */
   public static int getFaultCodeSeries(Exception e) {
      int code = 0;
      if ( e instanceof DBException )
         code = ((DBException)e).faultCode;
      else if ( e instanceof APIException )
         code = ((APIException)e).faultCode;
      // Strip it to the series
      code = code - ( code % 100 );
      return code;
   }

   /**
    * getFaultCode examines the provided exception to determine
    * the fault code that is associated with it.
    *
    * @param e The Exception to examine
    * @return The Fault Code
    */
   public static int getFaultCode(Exception e) {
      if ( e instanceof DBException )
         return ((DBException)e).faultCode;
      else if ( e instanceof APIException )
         return ((APIException)e).faultCode;
      else
         return 0;
   }

   /**
    * getFaultMessage examines the provided exception to determine
    * the fault message that is associated with it.
    *
    * @param e The Exception to examine
    * @return The Fault Message
    */
   public static String getFaultMessage(Exception e) {
      return getMessage(getFaultCode(e));
   }
}

