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.joran.action.Action; 032import ch.qos.logback.core.joran.action.ActionUtil; 033import ch.qos.logback.core.joran.action.TimestampAction; 034import ch.qos.logback.core.model.Model; 035import ch.qos.logback.core.model.TimestampModel; 036import ch.qos.logback.core.model.processor.ModelHandlerBase; 037import ch.qos.logback.core.model.processor.ModelHandlerException; 038import ch.qos.logback.core.model.processor.ModelInterpretationContext; 039import ch.qos.logback.core.util.CachingDateFormatter; 040import ch.qos.logback.core.util.OptionHelper; 041import ch.qos.logback.tyler.base.TylerModelInterpretationContext; 042import com.squareup.javapoet.MethodSpec; 043 044public class TimestampModelHandler extends ModelHandlerBase { 045 046 boolean inError = false; 047 static final String TIMESTAMP_METHOD_NAME = "timestamp"; 048 public TimestampModelHandler(Context context) { 049 super(context); 050 } 051 052 static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext ic) { 053 return new TimestampModelHandler(context); 054 } 055 056 057 @Override 058 protected Class<TimestampModel> getSupportedModelClass() { 059 return TimestampModel.class; 060 } 061 062 @Override 063 public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException { 064 TimestampModel timestampModel = (TimestampModel) model; 065 TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic; 066 String keyStr = timestampModel.getKey(); 067 if (OptionHelper.isNullOrEmptyOrAllSpaces(keyStr)) { 068 addError("Attribute named [" + Action.KEY_ATTRIBUTE + "] cannot be empty"); 069 inError = true; 070 } 071 072 String datePatternStr = timestampModel.getDatePattern(); 073 if (OptionHelper.isNullOrEmptyOrAllSpaces(datePatternStr)) { 074 addError("Attribute named [" + TimestampAction.DATE_PATTERN_ATTRIBUTE + "] cannot be empty"); 075 inError = true; 076 } 077 078 if(inError) { 079 addError("Skipping method generation for timestamp. Line " + model.getLineNumber()); 080 return; 081 } 082 083 addJavaStatement(tmic, timestampModel); 084 } 085 086 void addJavaStatement(TylerModelInterpretationContext tmic, TimestampModel timestampModel) { 087 String scopeStr = timestampModel.getScopeStr(); 088 if(scopeStr == null) { 089 scopeStr = ""; 090 } 091 final String keyStr = timestampModel.getKey(); 092 final String scopeVarName = "scope"; 093 final String datePatternStr = timestampModel.getDatePattern(); 094 final String cdfVarName = "cdf"; 095 final String timevalVarName = "timeValue"; 096 String timeReferenceVarName = "timeReference"; 097 098 final String timeReferenceStr = timestampModel.getTimeReference(); 099 100 101 102 MethodSpec.Builder timestampMethodSpecBuilder = MethodSpec.methodBuilder(toMethodName(keyStr)). 103 returns(void.class) 104 .addStatement("$T $N = $T.stringToScope($S)", ActionUtil.Scope.class, scopeVarName, ActionUtil.class, 105 scopeStr) 106 .addStatement("$1T $2N = new $1T($3S)", CachingDateFormatter.class, cdfVarName, datePatternStr); 107 108 if (TimestampModel.CONTEXT_BIRTH.equalsIgnoreCase(timeReferenceStr)) { 109 timestampMethodSpecBuilder.addStatement("addInfo(\"Using context birth as time reference.\""); 110 timestampMethodSpecBuilder.addStatement("long $N = $N.getBirthTime()", timeReferenceVarName, tmic.getContextFieldSpec()); 111 } else { 112 timestampMethodSpecBuilder.addStatement("long $N = System.currentTimeMillis()", timeReferenceVarName); 113 timestampMethodSpecBuilder.addStatement("addInfo(\"Using current interpretation time, i.e. now, as time reference.\")"); 114 } 115 116 timestampMethodSpecBuilder.addStatement("String $N = $N.format($N)", timevalVarName, cdfVarName, timeReferenceVarName); 117 118 timestampMethodSpecBuilder.addStatement("addInfo(\"Adding property to the context with key='\"+$S+\"' and value=\"+$N+\" to the \"+$N+\" scope\")" 119 , keyStr, timevalVarName, scopeVarName); 120 121 timestampMethodSpecBuilder.addStatement("$T.setProperty(this, $S, $N, $N)", ActionUtil.class, keyStr, timevalVarName, scopeVarName); 122 123 MethodSpec timestampMethodSpec = timestampMethodSpecBuilder.build(); 124 tmic.tylerConfiguratorTSB.addMethod(timestampMethodSpec); 125 tmic.configureMethodSpecBuilder.addStatement("$N()", timestampMethodSpec); 126 127 } 128 129 String toMethodName(String k) { 130 return TIMESTAMP_METHOD_NAME+'_'+k; 131 } 132}