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>This generated TylerConfigurator class is intended to be copied and integrated 
093                            into the user's project as a custom configurator. It will configure logback 
094                            without XML.</p>
095                                                
096                            <p>It requires logback-classic version %s or later at runtime.</p>
097                                                
098                            <p>Custom configurators are looked up via Java's service-provide facility. If a 
099                            custom provider is found, it takes precedence over logback's own configurators, 
100                            e.g. DefaultJoranConfigurator.</p>
101                                                
102                            <p>See also item 1 of 'Configuration at initialization' section at 
103                                                
104                                https://logback.qos.ch/manual/configuration.html#auto_configuration 
105                                                
106                            </p>
107                            """.formatted(TYLER_VERSION, REQUIRED_LOGBACK_VERSION))
108                    .addSuperinterface(Configurator.class)
109                    .superclass(TylerConfiguratorBase.class);
110            return tsb;
111        }
112
113        private MethodSpec.Builder initializeConfigureMethodSpecBuilder() {
114            MethodSpec.Builder msb = MethodSpec.methodBuilder(CONFIGURE_METHOD_NAME).addJavadoc("""
115                            <p>This method performs configuration per {@link $T} interface.</p>
116                                                
117                            <p>If <code>TylerConfigurator</code> is installed as a configurator service, this 
118                            method will be called by logback-classic during initialization.</p>
119                            """, Configurator.class).addAnnotation(Override.class).addModifiers(Modifier.PUBLIC)
120                    .addParameter(contextParameterSpec).returns(Configurator.ExecutionStatus.class)
121                    .addStatement("$N($N)", TylerConfiguratorBase.SET_CONTEXT_METHOD_NAME, contextParameterSpec);
122
123            return msb;
124        }
125
126        public FieldSpec getContextFieldSpec() {
127            return contextFieldSpec;
128        }
129    }