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