001package ch.qos.logback.tyler.base.handler;
002
003import ch.qos.logback.core.Context;
004import ch.qos.logback.core.model.Model;
005import ch.qos.logback.core.model.conditional.ByPropertiesConditionModel;
006import ch.qos.logback.core.model.processor.ModelHandlerBase;
007import ch.qos.logback.core.model.processor.ModelHandlerException;
008import ch.qos.logback.core.model.processor.ModelInterpretationContext;
009import ch.qos.logback.core.util.StringUtil;
010import ch.qos.logback.tyler.base.TylerModelInterpretationContext;
011import ch.qos.logback.tyler.base.util.ClassUtil;
012import ch.qos.logback.tyler.base.util.VariableNameUtil;
013import com.squareup.javapoet.ClassName;
014import com.squareup.javapoet.FieldSpec;
015import com.squareup.javapoet.MethodSpec;
016
017import static ch.qos.logback.tyler.base.TylerConstants.*;
018
019public class ByPropertiesConditionModelHandler extends ModelHandlerBase {
020
021    static int COUNT;
022    int instanceNum;
023    boolean inError = false;
024    ImplicitModelHandlerData implicitModelHandlerData;
025
026
027    public ByPropertiesConditionModelHandler(Context context) {
028        super(context);
029        instanceNum = COUNT++;
030    }
031
032
033    static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext mic) {
034        return new ByPropertiesConditionModelHandler(context);
035    }
036
037    @Override
038    public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
039        ByPropertiesConditionModel byPropertiesConditionModel = (ByPropertiesConditionModel) model;
040
041        TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic;
042
043        String originalClassName = byPropertiesConditionModel.getClassName();
044        String classNameStr = mic.getImport(originalClassName);
045        String conditionVariableName = VariableNameUtil.conditionModelToVariableName(classNameStr, instanceNum);
046        MethodSpec.Builder methodSpecBuilder = addJavaStatementForAppenderInitialization(tmic, conditionVariableName, classNameStr);
047
048
049        try {
050            Class<?> propertyConditionClass = Class.forName(classNameStr);
051            implicitModelHandlerData = new ImplicitModelHandlerData(propertyConditionClass, LOCAL_PROPERTY_CONDITION_FIELD_NAME, methodSpecBuilder);
052
053            mic.pushObject(implicitModelHandlerData);
054        } catch (ClassNotFoundException e) {
055            addError("Could not find class", e);
056            inError = true;
057        }
058    }
059
060    MethodSpec.Builder addJavaStatementForAppenderInitialization(TylerModelInterpretationContext tmic, String conditionVariableName,
061                                                                 String fullyQualifiedAppenderClassName) {
062
063        ClassName className = tmic.makeClassName(fullyQualifiedAppenderClassName);
064
065        String fistLetterCapitalizedConditionName = StringUtil.capitalizeFirstLetter(conditionVariableName);
066
067        String methodName = SETUP + fistLetterCapitalizedConditionName;
068        FieldSpec fieldSpec = tmic.createPropertyConditionFieldSpec(className, conditionVariableName);
069        tmic.getFieldSpecs().add(fieldSpec);
070
071        tmic.configureMethodSpecBuilder.addStatement("this.$N = $N()", conditionVariableName, methodName);
072
073        MethodSpec.Builder propertyConditionSetupMethodSpec = MethodSpec.methodBuilder(methodName).returns(className)
074                .addStatement("$1T $2N = new $1T()", className, LOCAL_PROPERTY_CONDITION_FIELD_NAME)
075                .addStatement("$N.setContext($N)", LOCAL_PROPERTY_CONDITION_FIELD_NAME, tmic.getContextFieldSpec())
076                .addJavadoc("Setup method for $N\n", conditionVariableName);
077
078        return propertyConditionSetupMethodSpec;
079    }
080
081
082    @Override
083    public void postHandle(ModelInterpretationContext mic, Model model) {
084        if (inError) {
085            return;
086        }
087
088        Object o = mic.peekObject();
089        if (o != implicitModelHandlerData) {
090            addWarn("The object at the of the stack is not the ImplicitModelHandlerData pushed earlier.");
091        } else {
092            TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic;
093            tmic.popObject();
094
095            MethodSpec.Builder propertyConditionMethodBuilder = implicitModelHandlerData.methodSpecBuilder;
096
097            String classNameStr = implicitModelHandlerData.parentObjectClass.getName();
098
099            String conditionVariableName = VariableNameUtil.conditionModelToVariableName(classNameStr, instanceNum);
100
101            // start the appender
102            propertyConditionMethodBuilder.addCode("\n");
103            propertyConditionMethodBuilder.addStatement("$N.start()", LOCAL_PROPERTY_CONDITION_FIELD_NAME);
104            propertyConditionMethodBuilder.addStatement("return $N", LOCAL_PROPERTY_CONDITION_FIELD_NAME);
105            MethodSpec propertyConditionMethodSpec = propertyConditionMethodBuilder.build();
106
107            tmic.tylerConfiguratorTSB.addMethod(propertyConditionMethodSpec);
108
109            mic.pushObject(new ConditionStringRecord("this."+conditionVariableName + ".evaluate()"));
110        }
111
112    }
113
114}