001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.log.render.txt; 020 021import com.fasterxml.jackson.annotation.JsonProperty; 022import org.jpos.log.LogRenderer; 023import org.jpos.log.evt.SysInfo; 024 025import java.io.PrintStream; 026import java.lang.reflect.RecordComponent; 027import java.util.LinkedHashMap; 028import java.util.List; 029import java.util.Map; 030 031public final class SysInfoTxtLogRenderer implements LogRenderer<SysInfo> { 032 public Class<?> clazz() { 033 return SysInfo.class; 034 } 035 public Type type() { 036 return Type.TXT; 037 } 038 039 @Override 040 public void render(SysInfo info, PrintStream ps, String indent) { 041 final String pre = (indent == null) ? "" : indent; 042 /* 043 * 1) Collect all record components in declaration order 044 * together with the effective (JSON) property name 045 * and the value obtained from the accessor. 046 */ 047 Map<String, Object> data = new LinkedHashMap<>(); 048 int maxKeyLen = 0; 049 050 for (RecordComponent rc : SysInfo.class.getRecordComponents()) { 051 String key = effectiveName(rc); 052 Object val; 053 try { 054 val = rc.getAccessor().invoke(info); 055 } catch (Exception e) { 056 val = "(error " + e.getMessage() + ")"; 057 } 058 data.put(key, val); 059 maxKeyLen = Math.max(maxKeyLen, key.length()); 060 } 061 062 final int width = maxKeyLen; 063 data.forEach((k, v) -> { 064 if (v == null) { // skip nulls 065 return; 066 } 067 if (v instanceof List<?> list) { 068 if (list.isEmpty()) { 069 return; 070 } 071 ps.printf("%s%-" + width + "s :%n", pre, k); 072 list.forEach(o -> ps.println(pre + " • " + o)); 073 } else { 074 ps.printf("%s%-" + width + "s : %s%n", pre, k, v); 075 } 076 }); 077 } 078 079 /** Returns the JSON alias if present, otherwise the plain component name. */ 080 private static String effectiveName(RecordComponent rc) { 081 JsonProperty jp = rc.getAnnotation(JsonProperty.class); 082 return (jp != null && !jp.value().isEmpty()) ? jp.value() : rc.getName(); 083 } 084} 085