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.Context; 031import ch.qos.logback.core.model.Model; 032import ch.qos.logback.core.model.StatusListenerModel; 033import ch.qos.logback.core.model.processor.ModelHandlerBase; 034import ch.qos.logback.core.model.processor.ModelHandlerException; 035import ch.qos.logback.core.model.processor.ModelInterpretationContext; 036import ch.qos.logback.core.spi.LifeCycle; 037import ch.qos.logback.core.util.OptionHelper; 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; 045 046public class StatusListenerModelHandler extends ModelHandlerBase { 047 048 static final String EFFECTIVELY_ADDED_VARIABLE_NAME = "effectivelyAdded"; 049 static int COUNT = 0; 050 final int instanceCount; 051 boolean inError = false; 052 ImplicitModelHandlerData implicitModelHandlerData; 053 054 public StatusListenerModelHandler(Context context) { 055 super(context); 056 instanceCount = COUNT++; 057 } 058 059 static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext mic) { 060 return new StatusListenerModelHandler(context); 061 } 062 063 public static void resetCount() { 064 COUNT = 0; 065 } 066 067 @Override 068 public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException { 069 070 StatusListenerModel slModel = (StatusListenerModel) model; 071 TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic; 072 073 String statusListenerClassName = slModel.getClassName(); 074 075 if (OptionHelper.isNullOrEmptyOrAllSpaces(statusListenerClassName)) { 076 addError("Empty class name for StatusListener"); 077 inError = true; 078 return; 079 } else { 080 statusListenerClassName = mic.getImport(statusListenerClassName); 081 } 082 083 MethodSpec.Builder methodSpec = addJavaStatement(tmic, statusListenerClassName); 084 this.implicitModelHandlerData = ImplicitModelHandlerData.makeInstance(this, methodSpec, statusListenerClassName); 085 if(implicitModelHandlerData != null) { 086 mic.pushObject(implicitModelHandlerData); 087 } else { 088 addError("Could not make implicitModelHandlerData for ["+statusListenerClassName+"]"); 089 model.markAsSkipped(); 090 inError = true; 091 } 092 } 093 094 MethodSpec.Builder addJavaStatement(TylerModelInterpretationContext tmic, 095 String statusListenerFQCN) { 096 097 098 String simpleName = ClassUtil.extractSimpleClassName(statusListenerFQCN); 099 100 ClassName desiredStatusListenerCN = ClassName.get(ClassUtil.extractPackageName(statusListenerFQCN), 101 simpleName); 102 103 String variableName = VariableNameUtil.fullyQualifiedClassNameToVariableName(statusListenerFQCN); 104 105 MethodSpec.Builder statusListenerSetupMethodSpec = MethodSpec.methodBuilder( 106 SETUP + simpleName + "_" +instanceCount).returns(void.class) 107 .addStatement("$1T $2N = new $1T()", desiredStatusListenerCN, variableName) 108 .addStatement("$N.setContext($N)", variableName, tmic.getContextFieldSpec()) 109 .addStatement("boolean $N = $N.getStatusManager().add($N)", EFFECTIVELY_ADDED_VARIABLE_NAME, 110 tmic.getContextFieldSpec(), variableName); 111 112 return statusListenerSetupMethodSpec; 113 } 114 115 @Override 116 public void postHandle(ModelInterpretationContext mic, Model model) { 117 if (inError) { 118 return; 119 } 120 121 Object o = mic.peekObject(); 122 if (o != implicitModelHandlerData) { 123 addWarn("The object at the of the stack is not the Implcit pushed earlier."); 124 } else { 125 TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic; 126 tmic.popObject(); 127 128 MethodSpec.Builder statusListenerMethodBuilder = implicitModelHandlerData.methodSpecBuilder; 129 130 String variableName = implicitModelHandlerData.getVariableName(); 131 132 statusListenerMethodBuilder.addCode("\n"); 133 statusListenerMethodBuilder.beginControlFlow("if($N && ($N instanceof $T))", EFFECTIVELY_ADDED_VARIABLE_NAME, variableName, LifeCycle.class); 134 statusListenerMethodBuilder.addStatement("(($T)$N).start()", LifeCycle.class, variableName); 135 statusListenerMethodBuilder.endControlFlow(); 136 MethodSpec statusListenerMethodSpec = statusListenerMethodBuilder.build(); 137 138 tmic.tylerConfiguratorTSB.addMethod(statusListenerMethodSpec); 139 140 tmic.configureMethodSpecBuilder.addStatement("$N()", statusListenerMethodSpec); 141 } 142 143 } 144} 145