/*
 * Copyright 1999-2005 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.logging.jdk.format;

import java.util.logging.Formatter;
import java.util.logging.LogRecord;

import org.jboss.logging.MDC;

// Contributors:   Nelson Minar <nelson@monkey.org>
//                 Anders Kristensen <akristensen@dynamicsoft.com>

/**
 * A flexible layout configurable with pattern string.
 * <p/>
 * <p>The goal of this class is to {@link #format format} a {@link
 * LogRecord} and return the results as a String. The results
 * depend on the <em>conversion pattern</em>.
 * <p/>
 * <p>The conversion pattern is closely related to the conversion
 * pattern of the printf function in C. A conversion pattern is
 * composed of literal text and format control expressions called
 * <em>conversion specifiers</em>.
 * <p/>
 * <p><i>You are free to insert any literal text within the conversion
 * pattern.</i>
 * <p/>
 * <p>Each conversion specifier starts with a percent sign (%) and is
 * followed by optional <em>format modifiers</em> and a <em>conversion
 * character</em>. The conversion character specifies the type of
 * data, e.g. category, priority, date, thread name. The format
 * modifiers control such things as field width, padding, left and
 * right justification. The following is a simple example.
 * <p/>
 * <p>Let the conversion pattern be <b>"%-5p [%t]: %m%n"</b> and assume
 * that the log4j environment was set to use a PatternLayout. Then the
 * statements
 * <pre>
 * Category root = Category.getRoot();
 * root.debug("Message 1");
 * root.warn("Message 2");
 * </pre>
 * would yield the output
 * <pre>
 * DEBUG [main]: Message 1
 * WARN  [main]: Message 2
 * </pre>
 * <p/>
 * <p>Note that there is no explicit separator between text and
 * conversion specifiers. The pattern parser knows when it has reached
 * the end of a conversion specifier when it reads a conversion
 * character. In the example above the conversion specifier
 * <b>%-5p</b> means the priority of the logging event should be left
 * justified to a width of five characters.
 * <p/>
 * The recognized conversion characters are
 * <p/>
 * <p/>
 * <table border="1" CELLPADDING="8">
 * <th>Conversion Character</th>
 * <th>Effect</th>
 * <p/>
 * <tr>
 * <td align=center><b>c</b></td>
 * <p/>
 * <td>Used to output the category of the logging event. The
 * category conversion specifier can be optionally followed by
 * <em>precision specifier</em>, that is a decimal constant in
 * brackets.
 * <p/>
 * <p>If a precision specifier is given, then only the corresponding
 * number of right most components of the category name will be
 * printed. By default the category name is printed in full.
 * <p/>
 * <p>For example, for the category name "a.b.c" the pattern
 * <b>%c{2}</b> will output "b.c".
 * <p/>
 * </td>
 * </tr>
 * <p/>
 * <tr>
 * <td align=center><b>C</b></td>
 * <p/>
 * <td>Used to output the fully qualified class name of the caller
 * issuing the logging request. This conversion specifier
 * can be optionally followed by <em>precision specifier</em>, that
 * is a decimal constant in brackets.
 * <p/>
 * <p>If a precision specifier is given, then only the corresponding
 * number of right most components of the class name will be
 * printed. By default the class name is output in fully qualified form.
 * <p/>
 * <p>For example, for the class name "org.apache.xyz.SomeClass", the
 * pattern <b>%C{1}</b> will output "SomeClass".
 * <p/>
 * <p><b>WARNING</b> Generating the caller class information is
 * slow. Thus, it's use should be avoided unless execution speed is
 * not an issue.
 * <p/>
 * </td>
 * </tr>
 * <p/>
 * <tr> <td align=center><b>d</b></td> <td>Used to output the date of
 * the logging event. The date conversion specifier may be
 * followed by a <em>date format specifier</em> enclosed between
 * braces. For example, <b>%d{HH:mm:ss,SSS}</b> or
 * <b>%d{dd&nbsp;MMM&nbsp;yyyy&nbsp;HH:mm:ss,SSS}</b>.  If no
 * date format specifier is given then ISO8601 format is
 * assumed.
 * <p/>
 * <p>The date format specifier admits the same syntax as the
 * time pattern string of the {@link
 * java.text.SimpleDateFormat}. Although part of the standard
 * JDK, the performance of <code>SimpleDateFormat</code> is
 * quite poor.
 * <p/>
 * <p>For better results it is recommended to use the log4j date
 * formatters. These can be specified using one of the strings
 * "ABSOLUTE", "DATE" and "ISO8601" for specifying {@link
 * AbsoluteTimeDateFormat
 * AbsoluteTimeDateFormat}, {@link
 * DateTimeDateFormat DateTimeDateFormat}
 * and respectively {@link
 * ISO8601DateFormat
 * ISO8601DateFormat}. For example, <b>%d{ISO8601}</b> or
 * <b>%d{ABSOLUTE}</b>.
 * <p/>
 * <p>These dedicated date formatters perform significantly
 * better than {@link java.text.SimpleDateFormat}.
 * </td>
 * </tr>
 * <p/>
 * <tr>
 * <td align=center><b>F</b></td>
 * <p/>
 * <td>Used to output the file name where the logging request was
 * issued.
 * <p/>
 * <p><b>WARNING</b> Generating caller location information is
 * extremely slow. It's use should be avoided unless execution speed
 * is not an issue.
 * <p/>
 * </tr>
 * <p/>
 * <tr>
 * <td align=center><b>l</b></td>
 * <p/>
 * <td>Used to output location information of the caller which generated
 * the logging event.
 * <p/>
 * <p>The location information depends on the JVM implementation but
 * usually consists of the fully qualified name of the calling
 * method followed by the callers source the file name and line
 * number between parentheses.
 * <p/>
 * <p>The location information can be very useful. However, it's
 * generation is <em>extremely</em> slow. It's use should be avoided
 * unless execution speed is not an issue.
 * <p/>
 * </td>
 * </tr>
 * <p/>
 * <tr>
 * <td align=center><b>L</b></td>
 * <p/>
 * <td>Used to output the line number from where the logging request
 * was issued.
 * <p/>
 * <p><b>WARNING</b> Generating caller location information is
 * extremely slow. It's use should be avoided unless execution speed
 * is not an issue.
 * <p/>
 * </tr>
 * <p/>
 * <p/>
 * <tr>
 * <td align=center><b>m</b></td>
 * <td>Used to output the application supplied message associated with
 * the logging event.</td>
 * </tr>
 * <p/>
 * <tr>
 * <td align=center><b>M</b></td>
 * <p/>
 * <td>Used to output the method name where the logging request was
 * issued.
 * <p/>
 * <p><b>WARNING</b> Generating caller location information is
 * extremely slow. It's use should be avoided unless execution speed
 * is not an issue.
 * <p/>
 * </tr>
 * <p/>
 * <tr>
 * <td align=center><b>n</b></td>
 * <p/>
 * <td>Outputs the platform dependent line separator character or
 * characters.
 * <p/>
 * <p>This conversion character offers practically the same
 * performance as using non-portable line separator strings such as
 * "\n", or "\r\n". Thus, it is the preferred way of specifying a
 * line separator.
 * <p/>
 * <p/>
 * </tr>
 * <p/>
 * <tr>
 * <td align=center><b>p</b></td>
 * <td>Used to output the priority of the logging event.</td>
 * </tr>
 * <p/>
 * <tr>
 * <p/>
 * <td align=center><b>r</b></td>
 * <p/>
 * <td>Used to output the number of milliseconds elapsed since the start
 * of the application until the creation of the logging event.</td>
 * </tr>
 * <p/>
 * <p/>
 * <tr>
 * <td align=center><b>t</b></td>
 * <p/>
 * <td>Used to output the name of the thread that generated the
 * logging event.</td>
 * <p/>
 * </tr>
 * <p/>
 * <tr>
 * <p/>
 * <td align=center><b>x</b></td>
 * <p/>
 * <td>Used to output the NDC (nested diagnostic context) associated
 * with the thread that generated the logging event.
 * </td>
 * </tr>
 * <p/>
 * <p/>
 * <tr>
 * <td align=center><b>X</b></td>
 * <p/>
 * <td>
 * <p/>
 * <p>Used to output the MDC (mapped diagnostic context) associated
 * with the thread that generated the logging event. The <b>X</b>
 * conversion character <em>must</em> be followed by the key for the
 * map placed between braces, as in <b>%X{clientNumber}</b> where
 * <code>clientNumber</code> is the key. The value in the MDC
 * corresponding to the key will be output.</p>
 * <p/>
 * <p>See {@link MDC} class for more details.
 * </p>
 * <p/>
 * </td>
 * </tr>
 * <p/>
 * <tr>
 * <p/>
 * <td align=center><b>%</b></td>
 * <p/>
 * <td>The sequence %% outputs a single percent sign.
 * </td>
 * </tr>
 * <p/>
 * </table>
 * <p/>
 * <p>By default the relevant information is output as is. However,
 * with the aid of format modifiers it is possible to change the
 * minimum field width, the maximum field width and justification.
 * <p/>
 * <p>The optional format modifier is placed between the percent sign
 * and the conversion character.
 * <p/>
 * <p>The first optional format modifier is the <em>left justification
 * flag</em> which is just the minus (-) character. Then comes the
 * optional <em>minimum field width</em> modifier. This is a decimal
 * constant that represents the minimum number of characters to
 * output. If the data item requires fewer characters, it is padded on
 * either the left or the right until the minimum width is
 * reached. The default is to pad on the left (right justify) but you
 * can specify right padding with the left justification flag. The
 * padding character is space. If the data item is larger than the
 * minimum field width, the field is expanded to accommodate the
 * data. The value is never truncated.
 * <p/>
 * <p>This behavior can be changed using the <em>maximum field
 * width</em> modifier which is designated by a period followed by a
 * decimal constant. If the data item is longer than the maximum
 * field, then the extra characters are removed from the
 * <em>beginning</em> of the data item and not from the end. For
 * example, it the maximum field width is eight and the data item is
 * ten characters long, then the first two characters of the data item
 * are dropped. This behavior deviates from the printf function in C
 * where truncation is done from the end.
 * <p/>
 * <p>Below are various format modifier examples for the category
 * conversion specifier.
 * <p/>
 * <p/>
 * <TABLE BORDER=1 CELLPADDING=8>
 * <th>Format modifier
 * <th>left justify
 * <th>minimum width
 * <th>maximum width
 * <th>comment
 * <p/>
 * <tr>
 * <td align=center>%20c</td>
 * <td align=center>false</td>
 * <td align=center>20</td>
 * <td align=center>none</td>
 * <p/>
 * <td>Left pad with spaces if the category name is less than 20
 * characters long.
 * <p/>
 * <tr> <td align=center>%-20c</td> <td align=center>true</td> <td
 * align=center>20</td> <td align=center>none</td> <td>Right pad with
 * spaces if the category name is less than 20 characters long.
 * <p/>
 * <tr>
 * <td align=center>%.30c</td>
 * <td align=center>NA</td>
 * <td align=center>none</td>
 * <td align=center>30</td>
 * <p/>
 * <td>Truncate from the beginning if the category name is longer than 30
 * characters.
 * <p/>
 * <tr>
 * <td align=center>%20.30c</td>
 * <td align=center>false</td>
 * <td align=center>20</td>
 * <td align=center>30</td>
 * <p/>
 * <td>Left pad with spaces if the category name is shorter than 20
 * characters. However, if category name is longer than 30 characters,
 * then truncate from the beginning.
 * <p/>
 * <tr>
 * <td align=center>%-20.30c</td>
 * <td align=center>true</td>
 * <td align=center>20</td>
 * <td align=center>30</td>
 * <p/>
 * <td>Right pad with spaces if the category name is shorter than 20
 * characters. However, if category name is longer than 30 characters,
 * then truncate from the beginning.
 * <p/>
 * </table>
 * <p/>
 * <p>Below are some examples of conversion patterns.
 * <p/>
 * <dl>
 * <p/>
 * <p><dt><b>%r [%t] %-5p %c %x - %m\n</b>
 * <p><dd>This is essentially the TTCC layout.
 * <p/>
 * <p><dt><b>%-6r [%15.15t] %-5p %30.30c %x - %m\n</b>
 * <p/>
 * <p><dd>Similar to the TTCC layout except that the relative time is
 * right padded if less than 6 digits, thread name is right padded if
 * less than 15 characters and truncated if longer and the category
 * name is left padded if shorter than 30 characters and truncated if
 * longer.
 * <p/>
 * </dl>
 * <p/>
 * <p>The above text is largely inspired from Peter A. Darnell and
 * Philip E. Margolis' highly recommended book "C -- a Software
 * Engineering Approach", ISBN 0-387-97389-3.
 *
 * @author <a href="mailto:cakalijp@Maritz.com">James P. Cakalic</a>
 * @author Ceki G&uuml;lc&uuml;
 * @author Scott.Stark@jboss.org
 * @version $Revision: 2786 $
 * 
 */
public class PatternFormatter extends Formatter
{

   /**
    * Default pattern string for log output. Currently set to the
    * string <b>"%m%n"</b> which just prints the application supplied
    * message.
    */
   public final static String DEFAULT_CONVERSION_PATTERN = "%m%n";

   /**
    * A conversion pattern equivalent to the TTCCCLayout.
    * Current value is <b>%r [%t] %p %c %x - %m%n</b>.
    */
   public final static String TTCC_CONVERSION_PATTERN
      = "%r [%t] %p %c %x - %m%n";


   protected final int BUF_SIZE = 256;
   protected final int MAX_CAPACITY = 1024;

   private String pattern;

   private PatternConverter head;

   /**
    * Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN.
    * <p/>
    * The default pattern just produces the application supplied message.
    */
   public PatternFormatter()
   {
      this(DEFAULT_CONVERSION_PATTERN);
   }

   /**
    * Constructs a PatternLayout using the supplied conversion pattern.
    * @param pattern 
    */
   public PatternFormatter(String pattern)
   {
      this.pattern = pattern;
      head = createPatternParser((pattern == null) ? DEFAULT_CONVERSION_PATTERN :
         pattern).parse();
   }

   /**
    * Set the <b>ConversionPattern</b> option. This is the string which
    * controls formatting and consists of a mix of literal content and
    * conversion specifiers.
    * @param conversionPattern 
    */
   public void setConversionPattern(String conversionPattern)
   {
      pattern = conversionPattern;
      head = createPatternParser(conversionPattern).parse();
   }

   /**
    * Returns the value of the <b>ConversionPattern</b> option.
    * @return the pattern
    */
   public String getConversionPattern()
   {
      return pattern;
   }

   /**
    * Does not do anything as options become effective
    */
   public void activateOptions()
   {
      // nothing to do.
   }

   /**
    * The PatternLayout does not handle the throwable contained within
    * {@link LogRecord LoggingEvents}. Thus, it returns
    * <code>true</code>.
    *
    * @return whether to ignore throwables
    * @since 0.8.4
    */
   public boolean ignoresThrowable()
   {
      return true;
   }

   /**
    * Returns PatternParser used to parse the conversion string. Subclasses
    * may override this to return a subclass of PatternParser which recognize
    * custom conversion characters.
    *
    * @param pattern the pattern
    * @return the parser
    * @since 0.9.0
    */
   protected PatternParser createPatternParser(String pattern)
   {
      return new PatternParser(pattern);
   }


   /**
    * Produces a formatted string as specified by the conversion pattern.
    */
   public String format(LogRecord event)
   {
      // output buffer appended to when format() is invoked
      StringBuffer sbuf = new StringBuffer(BUF_SIZE);
      PatternConverter c = head;
      while (c != null)
      {
         c.format(sbuf, event);
         c = c.next;
      }
      return sbuf.toString();
   }
}

