/*
 * Copyright 2018, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.logging;

import io.spine.base.Environment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.SubstituteLogger;

/**
 * Obtains {@link Logger} instance for a passed class and associates the value with the class.
 *
 * @author Alexander Yevsyukov
 */
class LoggerClassValue extends ClassValue<Logger> {

    private static final LoggerClassValue INSTANCE = new LoggerClassValue();

    static Logger getFor(Class<?> cls) {
        return INSTANCE.get(cls);
    }

    @Override
    protected Logger computeValue(Class<?> type) {
        Logger result = computeLogger(type);
        return result;
    }

    /**
     * Obtains or creates a logger for the passed class.
     *
     * @implNote If the code is executed under the {@linkplain Environment#isTests() tests},
     *           returned instance is new instance of a {@link SubstituteLogger},
     *           which redirects to a {@code Logger} obtained from
     *           {@link LoggerFactory#getLogger(Class) LoggerFactory}.
     */
    private static Logger computeLogger(Class<?> cls) {
        Logger logger = LoggerFactory.getLogger(cls);
        if (Environment.getInstance()
                       .isTests()) {
            SubstituteLogger substLogger = new SubstituteLogger(cls.getName(), null, true);
            substLogger.setDelegate(logger);
            return substLogger;
        }
        return logger;
    }
}

@@ -1067,16 +1067,84 @@
 onment;%0A
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;%0A
 import o
@@ -1234,16 +1234,66 @@
 eLogger;
+%0Aimport org.slf4j.helpers.SubstituteLoggerFactory;
 %0A%0A/**%0A *
@@ -1554,16 +1554,787 @@
 lue();%0A%0A
+    /**%0A     * The factory for logger instances when running under tests.%0A     *%0A     * %3Cp%3EIf this field is not-null, we're running under tests, and should produce%0A     * %7B@link org.slf4j.helpers.SubstituteLogger%7D instances, so that logging can be tested too.%0A     *%0A     * %3Cp%3EIf this field is %7B@code null%7D, we're under production mode, and return%0A     * %7B@link org.slf4j.Logger%7D obtained from %7B@link org.slf4j.LoggerFactory%7D without substitution.%0A     */%0A    private final @MonotonicNonNull SubstituteLoggerFactory substFactory;%0A%0A    private LoggerClassValue() %7B%0A        this.substFactory = Environment.getInstance()%0A                                       .isTests()%0A                            ? new SubstituteLoggerFactory()%0A                            : null;%0A    %7D%0A%0A
     stat
@@ -2952,23 +2952,16 @@
 private 
-static 
 Logger c
@@ -3059,67 +3059,28 @@
 if (
-Environment.getInstance()%0A                       .isTests()
+substFactory != null
 ) %7B%0A
@@ -3122,20 +3122,17 @@
 ogger = 
-new 
+(
 Substitu
@@ -3135,24 +3135,48 @@
 tituteLogger
+) substFactory.getLogger
 (cls.getName
@@ -3181,20 +3181,8 @@
 me()
-, null, true
 );%0A 

Create subst. loggers via factory