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