/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.log4j;

import org.apache.log4j.spi.LoggingEvent;

/**
 * This is a base class for LogMF and LogSF parameterized logging classes.
 *
 *
 * @see org.apache.log4j.LogMF
 * @see org.apache.log4j.LogSF
 * @since 1.2.16
 */
public abstract class LogXF {
    /**
     * Trace level.
     */
    protected static final Level TRACE = new Level(5000, "TRACE", 7);
    /**
     * Fully Qualified Class Name of this class.
     */
    private static final String FQCN = LogXF.class.getName();

    protected LogXF() {
    }

    /**
     * Returns a Boolean instance representing the specified boolean.
     * Boolean.valueOf was added in JDK 1.4.
     *
     * @param b a boolean value.
     * @return a Boolean instance representing b.
     */
    protected static Boolean valueOf(final boolean b) {
	if (b) {
	    return Boolean.TRUE;
	}
	return Boolean.FALSE;
    }

    /**
     * Returns a Character instance representing the specified char.
     * Character.valueOf was added in JDK 1.5.
     *
     * @param c a character value.
     * @return a Character instance representing c.
     */
    protected static Character valueOf(final char c) {
	return new Character(c);
    }

    /**
     * Returns a Byte instance representing the specified byte. Byte.valueOf was
     * added in JDK 1.5.
     *
     * @param b a byte value.
     * @return a Byte instance representing b.
     */
    protected static Byte valueOf(final byte b) {
	return new Byte(b);
    }

    /**
     * Returns a Short instance representing the specified short. Short.valueOf was
     * added in JDK 1.5.
     *
     * @param b a short value.
     * @return a Byte instance representing b.
     */
    protected static Short valueOf(final short b) {
	return new Short(b);
    }

    /**
     * Returns an Integer instance representing the specified int. Integer.valueOf
     * was added in JDK 1.5.
     *
     * @param b an int value.
     * @return an Integer instance representing b.
     */
    protected static Integer valueOf(final int b) {
	return new Integer(b);
    }

    /**
     * Returns a Long instance representing the specified long. Long.valueOf was
     * added in JDK 1.5.
     *
     * @param b a long value.
     * @return a Long instance representing b.
     */
    protected static Long valueOf(final long b) {
	return new Long(b);
    }

    /**
     * Returns a Float instance representing the specified float. Float.valueOf was
     * added in JDK 1.5.
     *
     * @param b a float value.
     * @return a Float instance representing b.
     */
    protected static Float valueOf(final float b) {
	return new Float(b);
    }

    /**
     * Returns a Double instance representing the specified double. Double.valueOf
     * was added in JDK 1.5.
     *
     * @param b a double value.
     * @return a Byte instance representing b.
     */
    protected static Double valueOf(final double b) {
	return new Double(b);
    }

    /**
     * Create new array.
     *
     * @param param1 parameter 1.
     * @return new array.
     */
    protected static Object[] toArray(final Object param1) {
	return new Object[] { param1 };
    }

    /**
     * Create new array.
     *
     * @param param1 parameter 1.
     * @param param2 parameter 2.
     * @return new array.
     */
    protected static Object[] toArray(final Object param1, final Object param2) {
	return new Object[] { param1, param2 };
    }

    /**
     * Create new array.
     *
     * @param param1 parameter 1.
     * @param param2 parameter 2.
     * @param param3 parameter 3.
     * @return new array.
     */
    protected static Object[] toArray(final Object param1, final Object param2, final Object param3) {
	return new Object[] { param1, param2, param3 };
    }

    /**
     * Create new array.
     *
     * @param param1 parameter 1.
     * @param param2 parameter 2.
     * @param param3 parameter 3.
     * @param param4 parameter 4.
     * @return new array.
     */
    protected static Object[] toArray(final Object param1, final Object param2, final Object param3,
	    final Object param4) {
	return new Object[] { param1, param2, param3, param4 };
    }

    /**
     * Log an entering message at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     */
    public static void entering(final Logger logger, final String sourceClass, final String sourceMethod) {
	if (logger.isDebugEnabled()) {
	    logger.callAppenders(
		    new LoggingEvent(FQCN, logger, Level.DEBUG, sourceClass + "." + sourceMethod + " ENTRY", null));
	}
    }

    /**
     * Log an entering message with a parameter at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     * @param param        parameter, may be null.
     */
    public static void entering(final Logger logger, final String sourceClass, final String sourceMethod,
	    final String param) {
	if (logger.isDebugEnabled()) {
	    String msg = sourceClass + "." + sourceMethod + " ENTRY " + param;
	    logger.callAppenders(new LoggingEvent(FQCN, logger, Level.DEBUG, msg, null));
	}
    }

    /**
     * Log an entering message with a parameter at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     * @param param        parameter, may be null.
     */
    public static void entering(final Logger logger, final String sourceClass, final String sourceMethod,
	    final Object param) {
	if (logger.isDebugEnabled()) {
	    String msg = sourceClass + "." + sourceMethod + " ENTRY ";
	    if (param == null) {
		msg += "null";
	    } else {
		try {
		    msg += param;
		} catch (Throwable ex) {
		    msg += "?";
		}
	    }
	    logger.callAppenders(new LoggingEvent(FQCN, logger, Level.DEBUG, msg, null));
	}
    }

    /**
     * Log an entering message with an array of parameters at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     * @param params       parameters, may be null.
     */
    public static void entering(final Logger logger, final String sourceClass, final String sourceMethod,
	    final Object[] params) {
	if (logger.isDebugEnabled()) {
	    String msg = sourceClass + "." + sourceMethod + " ENTRY ";
	    if (params != null && params.length > 0) {
		String delim = "{";
		for (int i = 0; i < params.length; i++) {
		    try {
			msg += delim + params[i];
		    } catch (Throwable ex) {
			msg += delim + "?";
		    }
		    delim = ",";
		}
		msg += "}";
	    } else {
		msg += "{}";
	    }
	    logger.callAppenders(new LoggingEvent(FQCN, logger, Level.DEBUG, msg, null));
	}
    }

    /**
     * Log an exiting message at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     */
    public static void exiting(final Logger logger, final String sourceClass, final String sourceMethod) {
	if (logger.isDebugEnabled()) {
	    logger.callAppenders(
		    new LoggingEvent(FQCN, logger, Level.DEBUG, sourceClass + "." + sourceMethod + " RETURN", null));
	}
    }

    /**
     * Log an exiting message with result at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     * @param result       result, may be null.
     */
    public static void exiting(final Logger logger, final String sourceClass, final String sourceMethod,
	    final String result) {
	if (logger.isDebugEnabled()) {
	    logger.callAppenders(new LoggingEvent(FQCN, logger, Level.DEBUG,
		    sourceClass + "." + sourceMethod + " RETURN " + result, null));
	}
    }

    /**
     * Log an exiting message with result at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     * @param result       result, may be null.
     */
    public static void exiting(final Logger logger, final String sourceClass, final String sourceMethod,
	    final Object result) {
	if (logger.isDebugEnabled()) {
	    String msg = sourceClass + "." + sourceMethod + " RETURN ";
	    if (result == null) {
		msg += "null";
	    } else {
		try {
		    msg += result;
		} catch (Throwable ex) {
		    msg += "?";
		}
	    }
	    logger.callAppenders(new LoggingEvent(FQCN, logger, Level.DEBUG, msg, null));
	}
    }

    /**
     * Logs a throwing message at DEBUG level.
     *
     * @param logger       logger, may not be null.
     * @param sourceClass  source class, may be null.
     * @param sourceMethod method, may be null.
     * @param thrown       throwable, may be null.
     */
    public static void throwing(final Logger logger, final String sourceClass, final String sourceMethod,
	    final Throwable thrown) {
	if (logger.isDebugEnabled()) {
	    logger.callAppenders(
		    new LoggingEvent(FQCN, logger, Level.DEBUG, sourceClass + "." + sourceMethod + " THROW", thrown));
	}
    }
}
