001    /*
002     * Copyright (c) 2024 QOS.ch Sarl (Switzerland)
003     * All rights reserved.
004     *
005     * Permission is hereby granted, free  of charge, to any person obtaining
006     * a  copy  of this  software  and  associated  documentation files  (the
007     * "Software"), to  deal in  the Software without  restriction, including
008     * without limitation  the rights to  use, copy, modify,  merge, publish,
009     * distribute,  sublicense, and/or sell  copies of  the Software,  and to
010     * permit persons to whom the Software  is furnished to do so, subject to
011     * the following conditions:
012     *
013     * The  above  copyright  notice  and  this permission  notice  shall  be
014     * included in all copies or substantial portions of the Software.
015     *
016     * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
017     * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
018     * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
019     * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
020     * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
021     * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
022     * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023     *
024     *
025     *
026     */
027
028    package ch.qos.logback.tyler.base;
029
030    import ch.qos.logback.classic.Level;
031    import ch.qos.logback.classic.LoggerContext;
032    import ch.qos.logback.classic.spi.Configurator;
033    import ch.qos.logback.classic.tyler.TylerConfiguratorBase;
034    import ch.qos.logback.core.Context;
035    import ch.qos.logback.core.model.processor.ModelInterpretationContext;
036    import ch.qos.logback.tyler.base.spi.StaticImportData;
037    import com.squareup.javapoet.FieldSpec;
038    import com.squareup.javapoet.MethodSpec;
039    import com.squareup.javapoet.ParameterSpec;
040    import com.squareup.javapoet.TypeSpec;
041
042    import javax.lang.model.element.Modifier;
043
044    import java.util.ArrayList;
045    import java.util.List;
046
047    import static ch.qos.logback.tyler.base.TylerConstants.CONFIGURE_METHOD_NAME;
048    import static ch.qos.logback.tyler.base.TylerConstants.CONTEXT_FIELD_NAME;
049    import static ch.qos.logback.tyler.base.TylerConstants.LEVEL_FIELD_NAME;
050    import static ch.qos.logback.tyler.base.TylerConstants.LOGGER_CONTEXT_PARAMETER_NAME;
051    import static ch.qos.logback.tyler.base.TylerConstants.REQUIRED_LOGBACK_VERSION;
052    import static ch.qos.logback.tyler.base.TylerConstants.TYLER_VERSION;
053
054    public class TylerModelInterpretationContext extends ModelInterpretationContext {
055
056        final public TypeSpec.Builder tylerConfiguratorTSB;
057        final public MethodSpec.Builder configureMethodSpecBuilder;
058
059        final FieldSpec contextFieldSpec = FieldSpec.builder(LoggerContext.class, CONTEXT_FIELD_NAME, Modifier.PRIVATE)
060                .build();
061        final ParameterSpec contextParameterSpec = ParameterSpec.builder(LoggerContext.class,
062                LOGGER_CONTEXT_PARAMETER_NAME).build();
063        final ParameterSpec levelParameterSpec = ParameterSpec.builder(Level.class, LEVEL_FIELD_NAME).build();
064
065        final List<StaticImportData> staticImportsList = new ArrayList<>();
066
067        public TylerModelInterpretationContext(Context context) {
068            super(context);
069            this.configureMethodSpecBuilder = initializeConfigureMethodSpecBuilder();
070            this.tylerConfiguratorTSB = initializeTylerConfiguratorTSB();
071        }
072
073        public void addStaticImport(StaticImportData sid) {
074            if (!staticImportsList.contains(sid))
075                staticImportsList.add(sid);
076        }
077
078        TypeSpec.Builder initializeTylerConfiguratorTSB() {
079            //MethodSpec setupLoggerMS = makeSetupLoggerMethodSpec();
080
081            TypeSpec.Builder tsb = TypeSpec.classBuilder(TylerConstants.TYLER_CONFIGURATOR).addJavadoc("""
082                                                
083                            <p>This file was generated by logback-tyler version %s</p>
084                            
085                            <p>Eventual errors and warnings are appended at the end.</p>                    
086                                                
087                            <p>You may experiment with logback.xml to Java translation, i.e. 
088                            TylerConfigurator generation, at the following URL:
089                                                
090                                  https://logback.qos.ch/translator/services/xml2Java.html </p>
091                                                
092                            <p>BEWARE: As of April 2024, TylerConfigurator generation from logback.xml 
093                            configuration files remains experimental and incomplete.
094                            </p>
095                                                
096                            <p>This generated TylerConfigurator class is intended to be copied and integrated 
097                            into the user's project as a custom configurator. It will configure logback 
098                            without XML.</p>
099                                                
100                            <p>It requires logback-classic version %s or later at runtime.</p>
101                                                
102                            <p>Custom configurators are looked up via Java's service-provide facility. If a 
103                            custom provider is found, it takes precedence over logback's own configurators, 
104                            e.g. DefaultJoranConfigurator.</p>
105                                                
106                            <p>See also item 1 of 'Configuration at initialization' section at 
107                                                
108                                https://logback.qos.ch/manual/configuration.html#auto_configuration 
109                                                
110                            </p>
111                            """.formatted(TYLER_VERSION, REQUIRED_LOGBACK_VERSION))
112                    .addSuperinterface(Configurator.class)
113                    .superclass(TylerConfiguratorBase.class);
114            return tsb;
115        }
116
117        private MethodSpec.Builder initializeConfigureMethodSpecBuilder() {
118            MethodSpec.Builder msb = MethodSpec.methodBuilder(CONFIGURE_METHOD_NAME).addJavadoc("""
119                            <p>This method performs configuration per {@link $T} interface.</p>
120                                                
121                            <p>If <code>TylerConfgiurator</code> is installed as a configurator service, this 
122                            method will be called by logback-classic during initialization.</p>
123                            """, Configurator.class).addAnnotation(Override.class).addModifiers(Modifier.PUBLIC)
124                    .addParameter(contextParameterSpec).returns(Configurator.ExecutionStatus.class)
125                    .addStatement("$N($N)", TylerConfiguratorBase.SET_CONTEXT_METHOD_NAME, contextParameterSpec);
126
127            return msb;
128        }
129
130        public FieldSpec getContextFieldSpec() {
131            return contextFieldSpec;
132        }
133    }