001// Generated by delombok at Sat Feb 25 17:58:34 UTC 2023
002package io.cui.tools.logging;
003
004import static io.cui.tools.logging.CuiLoggerFactory.MARKER_CLASS_NAMES;
005import static io.cui.tools.string.MoreStrings.lenientFormat;
006import static io.cui.tools.string.MoreStrings.nullToEmpty;
007import java.util.Comparator;
008import java.util.List;
009import java.util.function.Supplier;
010import java.util.logging.Level;
011import java.util.logging.Logger;
012import io.cui.tools.collect.CollectionLiterals;
013import io.cui.tools.reflect.MoreReflection;
014import lombok.NonNull;
015
016/**
017 * Defines the log-levels with implicit mapping
018 *
019 * @author Oliver Wolff
020 */
021public enum LogLevel {
022    /**
023     * Trace Level, maps to {@link Level#FINER}.
024     * <p>
025     * Attention: This is a derivation to
026     * http://www.slf4j.org/apidocs/org/slf4j/bridge/SLF4JBridgeHandler.html.
027     * But in fact this works...
028     */
029    TRACE(Level.FINER), /**
030     * Debug Level, maps to {@link Level#FINE}.
031     */
032    DEBUG(Level.FINE), /**
033     * Info Level, maps to {@link Level#INFO}.
034     */
035    INFO(Level.INFO), /**
036     * Warn Level, maps to {@link Level#WARNING}.
037     */
038    WARN(Level.WARNING), /**
039     * Error Level, maps to {@link Level#SEVERE}.
040     */
041    ERROR(Level.SEVERE), /**
042     * Off Level, maps to {@link Level#OFF}
043     */
044    OFF(Level.OFF);
045    private final Level juliLevel;
046
047    /**
048     * @param logger to be checked, must not be null
049     * @return {@code true} if the log-level is enabled on the logger, false otherwise
050     */
051    boolean isEnabled(final Logger logger) {
052        return logger.isLoggable(getJuliLevel());
053    }
054
055    /**
056     * Logs the message
057     *
058     * @param logger to be used, must not be null
059     * @param message must not be null
060     * @param throwable to be logged, may be null
061     */
062    void handleActualLog(final Logger logger, final String message, final Throwable throwable) {
063        if (!isEnabled(logger)) {
064            return;
065        }
066        doLog(logger, message, throwable);
067    }
068
069    /**
070     * @param juliLevel
071     * @return CUI log level
072     */
073    public static LogLevel from(@NonNull final Level juliLevel) {
074        if (juliLevel == null) {
075            throw new java.lang.NullPointerException("juliLevel is marked non-null but is null");
076        }
077        // highest value first, i.e. OFF, ERROR, WARN, INFO, DEBUG, TRACE
078        List<LogLevel> sortedCuiLevels = CollectionLiterals.mutableList(values());
079        sortedCuiLevels.sort(Comparator.comparing(logLevel -> logLevel.getJuliLevel().intValue()));
080        sortedCuiLevels.sort(Comparator.reverseOrder());
081        final var juliIntLevel = juliLevel.intValue();
082        for (LogLevel cuiLevel : sortedCuiLevels) {
083            final var cuiIntLevel = cuiLevel.getJuliLevel().intValue();
084            if (cuiIntLevel <= juliIntLevel) {
085                return cuiLevel;
086            }
087        }
088        return TRACE;
089    }
090
091    private void doLog(final Logger logger, final String message, final Throwable throwable) {
092        // We go up the stack-trace until we found the call from CuiLogger.
093        final var caller = MoreReflection.findCallerElement(throwable, MARKER_CLASS_NAMES);
094        if (caller.isPresent()) {
095            // This is needed because otherwise LogRecord will assume this class and this method as
096            // the source of the log-statement
097            logger.logp(getJuliLevel(), caller.get().getClassName(), caller.get().getMethodName(), message, throwable);
098        } else {
099            logger.log(getJuliLevel(), message, throwable);
100        }
101    }
102
103    // False positive, logger state explicitly checked
104    @SuppressWarnings("squid:S2629")
105    void log(final Logger logger, final String template, final Object... parameter) {
106        if (isEnabled(logger)) {
107            final var replacedTemplate = io.cui.tools.logging.CuiLogger.SLF4J_PATTERN.matcher(nullToEmpty(template)).replaceAll("%s");
108            doLog(logger, lenientFormat(replacedTemplate, parameter), null);
109        }
110    }
111
112    // False positive, logger state explicitly checked
113    @SuppressWarnings("squid:S2629")
114    void log(final Logger logger, Supplier<String> message, final Throwable throwable) {
115        if (isEnabled(logger)) {
116            doLog(logger, message.get(), throwable);
117        }
118    }
119
120    // False positive, logger state explicitly checked
121    @SuppressWarnings("squid:S2629")
122    void log(final Logger logger, final Throwable throwable, final String template, final Object... parameter) {
123        if (isEnabled(logger)) {
124            final var replacedTemplate = io.cui.tools.logging.CuiLogger.SLF4J_PATTERN.matcher(nullToEmpty(template)).replaceAll("%s");
125            doLog(logger, lenientFormat(replacedTemplate, parameter), throwable);
126        }
127    }
128
129    @java.lang.SuppressWarnings("all")
130    @lombok.Generated
131    private LogLevel(final Level juliLevel) {
132        this.juliLevel = juliLevel;
133    }
134
135    @java.lang.SuppressWarnings("all")
136    @lombok.Generated
137    Level getJuliLevel() {
138        return this.juliLevel;
139    }
140}