/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.logging;

/**
 * An extension of the JBoss Logger that adds a log()
 * primitive that maps to a dynamically defined log level.
 * 
 * TODO - Make sure serialization works correctly
 * 
 * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
 * @version <tt>$Revision: 1.1.2.2 $</tt>
 * 
 * @since 4.0.3
 */
public class DynamicLogger extends Logger
{
   private static final long serialVersionUID = -5963699806863917370L;
   
   /** The available log levels */
   public static final int LOG_LEVEL_NONE  = 0;
   public static final int LOG_LEVEL_FATAL = 1;
   public static final int LOG_LEVEL_ERROR = 2;
   public static final int LOG_LEVEL_WARN  = 3;
   public static final int LOG_LEVEL_INFO  = 4;
   public static final int LOG_LEVEL_DEBUG = 5;
   public static final int LOG_LEVEL_TRACE = 6;
   
   /** The available log level strings */
   public final static String[] LOG_LEVEL_STRINGS =
      { "NONE", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" }; 
    
   /** The log level to use for the "log" primitive */
   private int logLevel = LOG_LEVEL_DEBUG;
   
   /**
    * Protected CTOR
    */
   protected DynamicLogger(final String name)
   {
      super(name);
   }
   
   /////////////////////////////////////////////////////////////////////////
   //                            Factory Methods                          //
   /////////////////////////////////////////////////////////////////////////

   /**
    * Create a DynamicLogger instance given the logger name.
    *
    * @param name     the logger name
    */
   public static DynamicLogger getDynamicLogger(String name)
   {
      return new DynamicLogger(name);
   }

   /**
    * Create a DynamicLogger instance given the logger name with the given suffix.
    *
    * <p>This will include a logger seperator between classname and suffix
    *
    * @param name     The logger name
    * @param suffix   A suffix to append to the classname.
    */
   public static DynamicLogger getDynamicLogger(String name, String suffix)
   {
      return new DynamicLogger(name + "." + suffix);
   }

   /**
    * Create a DynamicLogger instance given the logger class. This simply
    * calls create(clazz.getName()).
    *
    * @param clazz    the Class whose name will be used as the logger name
    */
   public static DynamicLogger getDynamicLogger(Class clazz)
   {
      return new DynamicLogger(clazz.getName());
   }

   /**
    * Create a DynamicLogger instance given the logger class with the given suffix.
    *
    * <p>This will include a logger seperator between classname and suffix
    *
    * @param clazz    The Class whose name will be used as the logger name.
    * @param suffix   A suffix to append to the classname.
    */
   public static DynamicLogger getDynamicLogger(Class clazz, String suffix)
   {
      return new DynamicLogger(clazz.getName() + "." + suffix);
   }
   
   /////////////////////////////////////////////////////////////////////////
   //                         Extensions to Logger                        //
   /////////////////////////////////////////////////////////////////////////
   
   /**
    * Sets the logLevel for the log() primitive
    * 
    * @param logLevel between LOG_LEVEL_NONE and LOG_LEVEL_TRACE
    */
   public void setLogLevel(int logLevel)
   {
      if (logLevel >= LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_TRACE)
      {
         this.logLevel = logLevel;
      }
   }
   
   /**
    * Gets the logLevel of the log() primitive
    * 
    * @return the logLevel of the log() primitive
    */
   public int getLogLevel()
   {
      return logLevel;
   }
   
   /**
    * Sets the logLevel of the log() primitive
    * 
    * @param logLevelString the log level in String form
    */
   public void setLogLevelAsString(String logLevelString)
   {
      if (logLevelString != null)
      {
         logLevelString = logLevelString.toUpperCase().trim();
         
         for (int i = 0; i <= LOG_LEVEL_TRACE; i++)
         {
            if (logLevelString.equals(LOG_LEVEL_STRINGS[i]))
            {
               // match
               this.logLevel = i;
               break;
            }
         }
      }
   }
   
   /**
    * Gets the logLevel of the log() primitive in String form
    *
    * @return the logLevel of the log() primitive in String form
    */
   public String getLogLevelAsString()
   {
      return LOG_LEVEL_STRINGS[logLevel];
   }
   
   /**
    * Logs a message using dynamic log level
    * 
    * @param message the message to log
    */
   public void log(Object message)
   {
      switch (logLevel)
      {
         case LOG_LEVEL_TRACE:
            super.trace(message);
            break;
            
         case LOG_LEVEL_DEBUG:
            super.debug(message);
            break;
            
         case LOG_LEVEL_INFO:
            super.info(message);
            break;
            
         case LOG_LEVEL_WARN:
            super.warn(message);
            break;
            
         case LOG_LEVEL_ERROR:
            super.error(message);
            break;
            
         case LOG_LEVEL_FATAL:
            super.fatal(message);
            break;
            
         case LOG_LEVEL_NONE:
         default:
            // do nothing
            break;
      }
   }
   
   /**
    * Logs a message and a throwable using dynamic log level
    * @param message the message to log
    * @param t       the throwable to log
    */
   public void log(Object message, Throwable t)
   {
      switch (logLevel)
      {
         case LOG_LEVEL_TRACE:
            super.trace(message, t);
            break;
            
         case LOG_LEVEL_DEBUG:
            super.debug(message, t);
            break;
            
         case LOG_LEVEL_INFO:
            super.info(message, t);
            break;
            
         case LOG_LEVEL_WARN:
            super.warn(message, t);
            break;
            
         case LOG_LEVEL_ERROR:
            super.error(message, t);
            break;
            
         case LOG_LEVEL_FATAL:
            super.fatal(message, t);
            break;
            
         case LOG_LEVEL_NONE:
         default:
            // do nothing
            break;
      }      
   }
   
}
