Files
timi-utils/src/main/java/com/imyeyu/utils/AsciiTable.java
2025-07-12 12:45:46 +08:00

251 lines
5.8 KiB
Java

package com.imyeyu.utils;
import com.imyeyu.java.bean.CallbackArgReturn;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.java.ref.Ref;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 夜雨
* @since 2024-12-18 10:10
*/
public class AsciiTable<T> {
/** 制表符水平边框 */
private static final String BORDER_H = "";
/** 制表符垂直边框 */
private static final String BORDER_V = "";
/** 制表符左上边框 */
private static final String BORDER_TL = "";
/** 制表符上边框 */
private static final String BORDER_T = "";
/** 制表符右上边框 */
private static final String BORDER_TR = "";
/** 制表符左边框 */
private static final String BORDER_L = "";
/** 制表符十字边框 */
private static final String BORDER_P = "";
/** 制表符右边框 */
private static final String BORDER_R = "";
/** 制表符左下边框 */
private static final String BORDER_BL = "";
/** 制表符下边框 */
private static final String BORDER_B = "";
/** 制表符右下边框 */
private static final String BORDER_BR = "";
private final List<ColMapping<T>> colMappingList = new ArrayList<>();
private final List<Row> rowList = new ArrayList<>();
public String render(List<T> dataList) {
try {
{
// 表头
Row header = new Row();
for (int i = 0; i < colMappingList.size(); i++) {
Row.Col col = new Row.Col();
col.text = colMappingList.get(i).name;
header.colList.add(col);
}
rowList.add(header);
}
{
// 数据
for (int i = 0; i < dataList.size(); i++) {
Row row = new Row();
for (int j = 0; j < colMappingList.size(); j++) {
Row.Col col = new Row.Col();
Object objValue;
ColMapping<T> tColMapping = colMappingList.get(j);
if (tColMapping.itemCallback == null) {
objValue = Ref.getFieldValue(dataList.get(i), tColMapping.field, Object.class);
} else {
objValue = tColMapping.itemCallback.handler(dataList.get(i));
}
if (tColMapping.valueCallback != null) {
objValue = tColMapping.valueCallback.handler(objValue.toString());
}
col.text = objValue.toString();
row.colList.add(col);
}
rowList.add(row);
}
}
// 对齐渲染
Map<Integer, Integer> colMaxSize = new HashMap<>();
for (int i = 0; i < rowList.size(); i++) {
List<Row.Col> colList = rowList.get(i).colList;
for (int j = 0; j < colList.size(); j++) {
String colText = colList.get(j).text;
if (!colMaxSize.containsKey(j)) {
colMaxSize.put(j, colText.length());
}
colMaxSize.put(j, Math.max(colMaxSize.get(j), colText.length()));
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < rowList.size(); i++) {
List<Row.Col> colList = rowList.get(i).colList;
if (i == 0) {
// 顶边
sb.append(BORDER_TL);
for (int j = 0; j < colList.size(); j++) {
sb.append(BORDER_H.repeat(colMaxSize.get(j)));
if (j == colList.size() - 1) {
sb.append(BORDER_TR);
} else {
sb.append(BORDER_T);
}
}
sb.append('\n');
}
// 数据
for (int j = 0; j < colList.size(); j++) {
String text = colList.get(j).text;
if (j == 0) {
sb.append(BORDER_V);
}
sb.append(Text.paddedSpaceEnd(text, colMaxSize.get(j))).append(BORDER_V);
}
sb.append('\n');
if (i != rowList.size() - 1) {
// 数据分割
for (int j = 0; j < colList.size(); j++) {
if (j == 0) {
sb.append(BORDER_L);
}
sb.append(BORDER_H.repeat(colMaxSize.get(j)));
if (j == colList.size() - 1) {
sb.append(BORDER_R);
} else {
sb.append(BORDER_P);
}
}
sb.append('\n');
} else {
// 底边
sb.append(BORDER_BL);
for (int j = 0; j < colList.size(); j++) {
sb.append(BORDER_H.repeat(colMaxSize.get(j)));
if (j == colList.size() - 1) {
sb.append(BORDER_BR);
} else {
sb.append(BORDER_B);
}
}
}
}
return sb.toString();
} catch (IllegalAccessException e) {
throw new TimiException(TimiCode.ERROR, e.getMessage(), e);
}
}
public void addHeader(String field) {
addHeader(field.substring(0, 1).toUpperCase() + field.substring(1), field);
}
public void addHeader(String name, String field) {
TimiException.required(field, "not found field");
ColMapping<T> colMapping = new ColMapping<>();
colMapping.name = name;
colMapping.field = field;
colMappingList.add(colMapping);
}
public void addHeader(ColMapping<T> colMapping) {
colMappingList.add(colMapping);
}
/**
*
*
* @author 夜雨
* @since 2024-12-18 10:16
*/
public static class ColMapping<T> extends Row.Col {
private String name;
private String field;
private CallbackArgReturn<T, String> itemCallback;
private CallbackArgReturn<String, String> valueCallback;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public CallbackArgReturn<T, String> getItemCallback() {
return itemCallback;
}
public void setItemCallback(CallbackArgReturn<T, String> itemCallback) {
this.itemCallback = itemCallback;
}
public CallbackArgReturn<String, String> getValueCallback() {
return valueCallback;
}
public void setValueCallback(CallbackArgReturn<String, String> valueCallback) {
this.valueCallback = valueCallback;
}
}
/**
*
*
* @author 夜雨
* @since 2024-12-18 10:10
*/
private static class Row {
List<Col> colList = new ArrayList<>();
/**
*
*
* @author 夜雨
* @since 2024-12-18 10:10
*/
private static class Col {
String text;
}
}
}