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