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