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
028package ch.qos.logback.tyler.base.handler;
029
030import ch.qos.logback.core.Appender;
031import ch.qos.logback.core.Context;
032import ch.qos.logback.core.model.AppenderModel;
033import ch.qos.logback.core.model.Model;
034import ch.qos.logback.core.model.processor.ModelHandlerBase;
035import ch.qos.logback.core.model.processor.ModelHandlerException;
036import ch.qos.logback.core.model.processor.ModelInterpretationContext;
037import ch.qos.logback.core.util.StringUtil;
038import ch.qos.logback.tyler.base.TylerModelInterpretationContext;
039import ch.qos.logback.tyler.base.util.ClassUtil;
040import ch.qos.logback.tyler.base.util.VariableNameUtil;
041import com.squareup.javapoet.ClassName;
042import com.squareup.javapoet.FieldSpec;
043import com.squareup.javapoet.MethodSpec;
044
045import static ch.qos.logback.tyler.base.TylerConstants.*;
046
047public class AppenderModelHandler extends ModelHandlerBase {
048
049    ImplicitModelHandlerData implicitModelHandlerData;
050
051    private boolean skipped = false;
052    boolean inError = false;
053
054    public AppenderModelHandler(Context context) {
055        super(context);
056    }
057
058    @SuppressWarnings("rawtypes")
059    static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext mic) {
060        return new AppenderModelHandler(context);
061    }
062
063    @Override
064    @SuppressWarnings("unchecked")
065    public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
066
067        AppenderModel appenderModel = (AppenderModel) model;
068
069        TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic;
070
071        String appenderName = tmic.subst(appenderModel.getName());
072
073        String originalClassName = appenderModel.getClassName();
074        String className = mic.getImport(originalClassName);
075
076        MethodSpec.Builder methodSpec = addJavaStatementForAppenderInitialization(tmic, appenderName, className);
077        try {
078            Class appenderClass = Class.forName(className);
079            implicitModelHandlerData = new ImplicitModelHandlerData(appenderClass, LOCAL_APPENDER_FIELD_NAME, methodSpec);
080
081            mic.pushObject(implicitModelHandlerData);
082        } catch (ClassNotFoundException e) {
083            addError("Could not find class", e);
084            inError = true;
085        }
086
087    }
088
089    MethodSpec.Builder addJavaStatementForAppenderInitialization(TylerModelInterpretationContext tmic, String appenderName,
090                    String fullyQualifiedAppenderClassName) {
091
092        ClassName desiredAppenderCN = tmic.makeClassName(fullyQualifiedAppenderClassName);
093
094        String fistLetterCapitalizedAppenderName = StringUtil.capitalizeFirstLetter(appenderName);
095
096        String methodName = SETUP_APPENDER + fistLetterCapitalizedAppenderName;
097        String appenderVariableName = VariableNameUtil.appenderNameToVariableName(appenderName);
098        FieldSpec fieldSpec = tmic.createAppenderFieldSpec(desiredAppenderCN, appenderName);
099        tmic.getFieldSpecs().add(fieldSpec);
100
101        tmic.configureMethodSpecBuilder.addStatement("this.$N = $N()", appenderVariableName, methodName);
102
103        MethodSpec.Builder appenderSetupMethodSpec = MethodSpec.methodBuilder(methodName).returns(desiredAppenderCN)
104                        .addStatement("$1T $2N = new $1T()", desiredAppenderCN, LOCAL_APPENDER_FIELD_NAME)
105                        .addStatement("$N.setContext($N)", LOCAL_APPENDER_FIELD_NAME, tmic.getContextFieldSpec())
106                        .addStatement("$N.setName($S)", LOCAL_APPENDER_FIELD_NAME, appenderName);
107
108        return appenderSetupMethodSpec;
109    }
110
111    @Override
112    public void postHandle(ModelInterpretationContext mic, Model model) {
113        if (inError) {
114            return;
115        }
116
117        Object o = mic.peekObject();
118        if (o != implicitModelHandlerData) {
119            addWarn("The object at the of the stack is not the ImplicitModelHandlerData pushed earlier.");
120        } else {
121            TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic;
122            tmic.popObject();
123
124            MethodSpec.Builder appenderMethodBuilder = implicitModelHandlerData.methodSpecBuilder;
125
126            // start the appender
127            appenderMethodBuilder.addCode("\n");
128            appenderMethodBuilder.addStatement("$N.start()", LOCAL_APPENDER_FIELD_NAME);
129            appenderMethodBuilder.addStatement("return $N", LOCAL_APPENDER_FIELD_NAME);
130            MethodSpec appenderMethodSpec = appenderMethodBuilder.build();
131
132            tmic.tylerConfiguratorTSB.addMethod(appenderMethodSpec);
133
134        }
135
136    }
137}