package jnpf.bizcommon.audit.service.value;
import com.alibaba.fastjson.JSON;
import jnpf.bizcommon.audit.entity.model.AuditFieldDiffViewVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
/**
* 按 JNPF dictionaryType 批量解析字典项;一次详情至多执行一条字典查询。
*
*
{@code @Order} 的含义见 {@link LimsQingyandanFieldValueResolver} 的类注释。
*/
@Slf4j
@Component
@Order(JnpfDictionaryFieldValueResolver.ORDER)
public class JnpfDictionaryFieldValueResolver implements AuditFieldValueResolver {
/** 平台通用解析器,排在表专用(100)之后、用户兜底(300)之前。 */
public static final int ORDER = 200;
private static final String UNAVAILABLE = "名称暂不可用";
private final DictionaryLookup lookup;
@Autowired
public JnpfDictionaryFieldValueResolver(JdbcTemplate jdbcTemplate) {
this(new JdbcDictionaryLookup(jdbcTemplate));
}
JnpfDictionaryFieldValueResolver(DictionaryLookup lookup) {
this.lookup = lookup;
}
@Override
public boolean supports(String targetTable) {
return true;
}
@Override
public void resolve(AuditFieldValueContext context, List fields) {
if (context == null || blank(context.getTenantId()) || fields == null || fields.isEmpty()
|| context.getDictionaryTypes().isEmpty()) {
return;
}
Set dictionaryTypes = new LinkedHashSet<>();
Set values = new LinkedHashSet<>();
for (AuditFieldDiffViewVO field : fields) {
String dictionaryType = dictionaryType(context, field);
if (dictionaryType == null || displaysResolved(field)) {
continue;
}
dictionaryTypes.add(dictionaryType);
values.addAll(parseValues(field.getOldData()));
values.addAll(parseValues(field.getNewData()));
}
if (dictionaryTypes.isEmpty() || values.isEmpty()) {
return;
}
Map> labels = lookup.labels(
context.getTenantId().trim(), dictionaryTypes, values);
for (AuditFieldDiffViewVO field : fields) {
String dictionaryType = dictionaryType(context, field);
Map dictionary = dictionaryType == null
? null : labels.get(dictionaryType);
if (dictionary == null) {
continue;
}
boolean multiple = "multiEnum".equals(field.getValueType())
|| startsWithArray(field.getOldData()) || startsWithArray(field.getNewData());
if (blank(field.getValueType())) {
field.setValueType(multiple ? "multiEnum" : "enum");
}
if (field.getOldDisplay() == null) {
field.setOldDisplay(display(field.getOldData(), dictionary));
}
if (field.getNewDisplay() == null) {
field.setNewDisplay(display(field.getNewData(), dictionary));
}
}
}
private static String dictionaryType(AuditFieldValueContext context, AuditFieldDiffViewVO field) {
if (field == null || blank(field.getField())) {
return null;
}
return context.getDictionaryTypes().get(field.getField().trim().toLowerCase(Locale.ROOT));
}
private static boolean displaysResolved(AuditFieldDiffViewVO field) {
return (blank(field.getOldData()) || field.getOldDisplay() != null)
&& (blank(field.getNewData()) || field.getNewDisplay() != null);
}
private static String display(String raw, Map labels) {
if (blank(raw)) {
return "";
}
List values = parseValues(raw);
if (values.isEmpty()) {
return UNAVAILABLE;
}
List result = new ArrayList<>(values.size());
for (String value : values) {
String label = labels.get(value);
result.add(blank(label) ? UNAVAILABLE : label);
}
return String.join("、", result);
}
@SuppressWarnings("unchecked")
private static List parseValues(String raw) {
if (blank(raw)) {
return Collections.emptyList();
}
String trimmed = raw.trim();
if (!trimmed.startsWith("[")) {
return Collections.singletonList(trimmed);
}
try {
Object parsed = JSON.parse(trimmed);
if (!(parsed instanceof Collection)) {
return Collections.emptyList();
}
List result = new ArrayList<>();
for (Object value : (Collection