io.github.aritzhack.aritzh.logging.LogFormatter.java Source code

Java tutorial

Introduction

Here is the source code for io.github.aritzhack.aritzh.logging.LogFormatter.java

Source

/*
 * Copyright 2015 Aritz Lopez
 *
 *    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 io.github.aritzhack.aritzh.logging;

import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import io.github.aritzhack.aritzh.logging.core.LogLevel;
import io.github.aritzhack.aritzh.util.NotNull;
import io.github.aritzhack.aritzh.util.Nullable;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * @author Aritz Lopez
 */
public enum LogFormatter {
    ;

    private static final DateFormat DF = new SimpleDateFormat("HH:mm:ss.SSS");

    private static final char TOKEN_MESSAGE = 'm';
    private static final char TOKEN_DATE = 'd';
    private static final char TOKEN_LEVEL = 'l';
    private static final char TOKEN_FULL_LEVEL = 'L';
    private static final char TOKEN_THROWABLE = 'e';
    private static final char TOKEN_THREAD = 't';
    private static final char TOKEN_NAME = 'n';

    private static final char BEGIN_TOKEN = '%';
    private static final char BEGIN_CONDITION = '?';
    private static final char DELIMITER_LEFT = '{';
    private static final char DELIMITER_RIGHT = '}';

    private static final Map<String, DateFormat> dateFormats = Maps.newHashMap();

    public static String formatLogMessage(@NotNull LogLevel level, @NotNull String format, @Nullable String message,
            @Nullable String loggerName) {
        return LogFormatter.formatLogMessage(level, format, message, null, loggerName);
    }

    public static String formatLogMessage(@NotNull LogLevel level, @NotNull String format, @Nullable String message,
            @Nullable Throwable t, @Nullable String loggerName) {
        boolean inCondition = false;
        boolean conditionMet = false;
        StringBuilder out = new StringBuilder();

        char[] chars = format.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            boolean notLast = i < chars.length - 1;
            char c = chars[i];

            // Check for ending the condition environment
            if (inCondition && c == DELIMITER_RIGHT) {
                inCondition = false;
                conditionMet = false;
                continue;
            }

            // Skip if the condition is unmet
            if (inCondition && !conditionMet)
                continue;

            if (c == BEGIN_TOKEN && notLast) { // Check if we are in a replace-token
                i++;
                c = chars[i];
                switch (c) {
                case BEGIN_TOKEN:
                    out.append(BEGIN_TOKEN);
                    break;
                case TOKEN_MESSAGE:
                    out.append(message);
                    break;
                case TOKEN_DATE:
                    if (notLast && chars[i + 1] == DELIMITER_LEFT) {
                        i++;
                        String dFormat = "";
                        while (i < chars.length - 1) {
                            i++;
                            c = chars[i];
                            if (c == DELIMITER_RIGHT)
                                break;
                            dFormat += c;
                        }
                        if (!dateFormats.containsKey(dFormat)) {
                            dateFormats.put(dFormat, new SimpleDateFormat(dFormat));
                        }
                        out.append(dateFormats.get(dFormat).format(new Date()));
                    } else {
                        out.append(DF.format(new Date()));
                    }
                    break;
                case TOKEN_LEVEL:
                    out.append(level.name());
                    break;
                case TOKEN_FULL_LEVEL:
                    out.append("[").append(level.name()).append("]");
                    out.append(Strings.repeat(" ", LogLevel.maxNameLength - level.name().length()));
                    break;
                case TOKEN_THROWABLE:
                    if (t != null) {
                        out.append(Throwables.getStackTraceAsString(t));
                    }
                    break;
                case TOKEN_THREAD:
                    out.append(Thread.currentThread().getName());
                    break;
                case TOKEN_NAME:
                    out.append(loggerName);
                    break;
                }
            } else if (c == BEGIN_CONDITION) { // Check if we are starting a condition environment
                inCondition = true;

                // Read the condition
                String condition = "";

                while (i < chars.length - 1) { // Safe-check not to get an ArrayIndexOutOfBoundsException
                    i++;
                    c = chars[i];
                    if (c == DELIMITER_LEFT)
                        break; // If we reach the beginning if the environment, stop
                    condition += c;
                }

                // Parse the condition
                if (condition.equalsIgnoreCase(toS(TOKEN_THROWABLE))) {
                    conditionMet = t != null;
                } else if (condition.startsWith(toS(TOKEN_LEVEL)) || condition.startsWith(toS(TOKEN_FULL_LEVEL))) {
                    String cLevel = condition.substring(1);
                    conditionMet = LogLevel.getLevel(cLevel) == level;
                } else if (condition.equalsIgnoreCase(toS(TOKEN_MESSAGE))) {
                    conditionMet = !Strings.isNullOrEmpty(message);
                } else if (condition.equalsIgnoreCase(toS(TOKEN_NAME))) {
                    conditionMet = !Strings.isNullOrEmpty(loggerName);
                }
            } else {
                out.append(c);
            }
        }
        return out.toString();
    }

    private static String toS(char c) {
        return String.valueOf(c);
    }
}