ic_excellent 2023-03-15 16:14:48 +08:00
commit f71d0dbe18
870 changed files with 141578 additions and 2073 deletions

1
.gitignore vendored
View File

@ -46,4 +46,5 @@ src/test/resources/font
src/main/resources/WEB-INF/vm/outFile src/main/resources/WEB-INF/vm/outFile
target/ target/
*.back *.back
src/main/old_src/

View File

@ -47,6 +47,8 @@ jQuery().ready(function(){
} }
} }
addRowBack(2, configObj);
changeDetailFieldReadOnly(detailTable, detail2ComPayDateId, detail2PaymentTypeId, computeDatePayType) changeDetailFieldReadOnly(detailTable, detail2ComPayDateId, detail2PaymentTypeId, computeDatePayType)
// 主表字段发生变化 // 主表字段发生变化

View File

@ -42,6 +42,8 @@ function getDate(time) {
return y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d); return y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d);
} }
/** /**
* 校验比例是否等于100 * 校验比例是否等于100
* @param detailTable 明细表 * @param detailTable 明细表
@ -153,6 +155,18 @@ function changeDetailPayDate(obj){
} }
} }
/**
* 字段联动后添加明细行后执行的逻辑
* @param detail
* @param configObj
*/
function addRowBack(detail, configObj){
WfForm.registerAction(WfForm.ACTION_ADDROW + detail, function(index){
configObj.index = index;
changeDetailPayDate(configObj);
});
}
/** /**
* 改变明细表字段只读 * 改变明细表字段只读
* @param detailTable * @param detailTable
@ -173,3 +187,5 @@ function changeDetailFieldReadOnly(detailTable, detailComDateField, detailPaymen
} }
} }
} }

View File

@ -0,0 +1,31 @@
// 存货分类编码
const chflbmId = WfForm.convertFieldNameToId("chflbm");
// 流程类型
const workflowType = WfForm.convertFieldNameToId("lcxz");
// 唯一编码
const unqieCode = WfForm.convertFieldNameToId("wybm");
// 帐套查询
const zt = WfForm.convertFieldNameToId("ztcx");
// 存货编码
const chbm = WfForm.convertFieldNameToId("chbm2");
changeVal();
WfForm.bindFieldChangeEvent(chflbmId, function(obj,id,value){
changeVal();
});
function changeVal(){
let value = WfForm.getFieldValue(chflbmId)
console.log('value: ', value);
if(!value){
return;
}
let firstVal = value.charAt(0);
if(firstVal == 0){
value = value.substring(1, value.length);
console.log('修改后的val ', value);
setTimeout(()=>{
$(`#${chflbmId}span`)[0].innerHTML = value;
},5);
}
}

View File

@ -0,0 +1,32 @@
// 主表预计付款日期
const yjfksj = WfForm.convertFieldNameToId('yjfksj');
// 主表比例
const bl = WfForm.convertFieldNameToId('bcfkbl');
// 明细要求付款日期
const detail3Yqfkrq = WfForm.convertFieldNameToId('yqfkrq',"detail_3");
// 明细本次付款比例
const detailBl = WfForm.convertFieldNameToId('bcfkbl',"detail_3");
WfForm.registerCheckEvent(WfForm.OPER_ADDROW + "3", function (callback) {
callback();
initDeatail3Date();
});
WfForm.bindFieldChangeEvent(`${yjfksj},${bl}`, function(obj,id,value){
initDeatail3Date();
});
function initDeatail3Date(){
let dateVal = WfForm.getFieldValue(yjfksj);
let blVal = WfForm.getFieldValue(bl);
console.log('dateVal ', dateVal);
console.log('blVal ', blVal);
let detail3RowArr = WfForm.getDetailAllRowIndexStr('detail_3').split(",");
for (let i = 0; i < detail3RowArr.length; i++) {
let rowIndex = detail3RowArr[i];
if (rowIndex !== "") {
WfForm.changeFieldValue(`${detail3Yqfkrq}_${rowIndex}`,{value: dateVal});
WfForm.changeFieldValue(`${detailBl}_${rowIndex}`,{value: blVal});
}
}
}

View File

@ -0,0 +1,217 @@
var m_xmmc = WfForm.convertFieldNameToId("xmmc");//项目名称
var m_bmwyz = WfForm.convertFieldNameToId("glkcjlb");//关联勘察
var m_bmwyz1 = WfForm.convertFieldNameToId("glxsxqd");//关联销售
var m_bmwyz2 = WfForm.convertFieldNameToId("chdadx");//唯一值多选
var dt2_tyrq = WfForm.convertFieldNameToId("tyrq", "detail_2");//明细2停用日期
jQuery(document).ready(function () {
setTimeout("bindFieldChange()", "500");
});
function bindFieldChange() {
WfForm.bindFieldChangeEvent(m_xmmc, function (obj, id, value) {
WfForm.changeFieldValue(m_bmwyz, {value: ''});
WfForm.changeFieldValue(m_bmwyz1, {value: ''});
WfForm.changeFieldValue(m_bmwyz2, {value: ''});
});
//提交检验
WfForm.registerCheckEvent(WfForm.OPER_SUBMIT, function (callback) {
var flag = true;
var rowArr = WfForm.getDetailAllRowIndexStr("detail_2").split(",");
for (var i = 0; i < rowArr.length; i++) {
var rowid = rowArr[i];
var dt2_tyrq_v = WfForm.getFieldValue(dt2_tyrq + "_" + rowid);
if (dt2_tyrq_v != "") {
WfForm.showMessage("明细2第" + (i + 1) + "行设备已在" + dt2_tyrq_v + "停用!", 2, 5);
flag = flase;
break;
}
}
if (flag) {
callback(); //继续提交需调用callback不调用代表阻断
}
});
}
var rowArr = WfForm.getDetailAllRowIndexStr("detail_3").split(",");
// WfForm.delDetailRow("detail_2", "all");
for (var i = 0; i < rowArr.length; i++) {
var rowIndex = rowArr[i];
if (rowIndex !== "") {
var fieldMark = "field12566" + rowIndex;
if (fieldMark === "0") {
var count = WfForm.getFieldValue("field12562" + rowIndex);
var field7108_ = WfForm.getFieldValue("field6117_" + rowIndex);
WfForm.addDetailRow("detail_2", {field8567: {value: count}, field7583: {value: field7108_},});
}
}
}
/*
dev-1 王宣然 限制明细表选择的bom不能重复
*/
const detailBomField = WfForm.convertFieldNameToId('bombm', 'detail_1');
/**
* 主表辅助字段
*/
const mainAttrField = WfForm.convertFieldNameToId('ycbmpzx');
/**
* 明细1数量
*/
const detail1NumFieldId = WfForm.convertFieldNameToId('sl1', "detail_1");
/**
* 明细3 明细2数量
*/
const detail3NumFieldId = WfForm.convertFieldNameToId('mx2sl', "detail_3");
/**
* 明细3数量
*/
const detail3NumFieldId2 = WfForm.convertFieldNameToId('sl1', "detail_3");
/**
* 明细3需求数量
*/
const detail3NumFieldId3 = WfForm.convertFieldNameToId('sl', "detail_3");
/**
* 明细3bom编码
*/
const detail3BomFieldId = WfForm.convertFieldNameToId('bombm', "detail_3");
/**
* 明细1bom编码
*/
const detail1BomFieldId = WfForm.convertFieldNameToId('bombm', "detail_1");
/*
*已经选择的bom
*/
let choiceArr = new Set();
let updateNum = {};
const yjdhrq = WfForm.convertFieldNameToId('yjdhrq');
console.log('id ', yjdhrq)
// 明细到货日期
const detail1yjdhsj = WfForm.convertFieldNameToId('yjdhsj', "detail_2");
WfForm.bindFieldChangeEvent(yjdhrq, function (obj, id, value) {
initDeatail2Date(value);
});
WfForm.registerCheckEvent(WfForm.OPER_ADDROW + "2", function (callback) {
callback();
let value = WfForm.getFieldValue(yjdhrq);
initDeatail2Date(value);
});
WfForm.bindDetailFieldChangeEvent(detailBomField, function (id, rowIndex, value) {
if (!value) {
return;
}
if (choiceArr.has(value)) {
WfForm.showMessage('不能选择重复的bom请重新选择!');
setTimeout(() => {
WfForm.changeFieldValue(`${detailBomField}_${rowIndex}`, {value: '', specialobj: []});
}, 5);
}
initChoiceArr();
getBomArr();
});
// 数量变化自动计算
WfForm.bindDetailFieldChangeEvent(`${detail1NumFieldId},${detailBomField}`, function (id, rowIndex, value) {
let detail1RowArr = WfForm.getDetailAllRowIndexStr('detail_1').split(",");
console.log(detail1RowArr);
for (let i = 0; i < detail1RowArr.length; i++) {
let rowIndex = detail1RowArr[i];
if (rowIndex !== "") {
let num = WfForm.getFieldValue(`${detail1NumFieldId}_${rowIndex}`);
// bom编码
let bom = WfForm.getFieldValue(`${detail1BomFieldId}_${rowIndex}`);
setTimeout(() => {
computeNum(bom, num);
}, 500);
}
}
});
function initDeatail2Date(value) {
let detail2RowArr = WfForm.getDetailAllRowIndexStr('detail_2').split(",");
for (let i = 0; i < detail2RowArr.length; i++) {
let rowIndex = detail2RowArr[i];
if (rowIndex !== "") {
WfForm.changeFieldValue(`${detail1yjdhsj}_${rowIndex}`, {value: value});
}
}
}
/**
* 计算明细3数量
*/
function computeNum(detail1Bom, detail1Num) {
let detail3RowArr = WfForm.getDetailAllRowIndexStr('detail_3').split(",");
console.log(detail3RowArr);
for (let i = 0; i < detail3RowArr.length; i++) {
let rowIndex = detail3RowArr[i];
if (rowIndex !== "") {
// bom编码
let bom = WfForm.getFieldValue(`${detail3BomFieldId}_${rowIndex}`);
if (bom != detail1Bom) {
continue;
}
console.log('需要改变的index ', rowIndex)
WfForm.changeFieldValue(`${detail3NumFieldId}_${rowIndex}`, {value: detail1Num});
}
}
}
/**
* 初始化已经选择的数组
*/
function initChoiceArr() {
choiceArr = new Set();
let rowArr = WfForm.getDetailAllRowIndexStr('detail_1').split(",");
for (let i = 0; i < rowArr.length; i++) {
let rowIndex = rowArr[i];
if (rowIndex !== "") {
let bom = WfForm.getFieldValue(`${detailBomField}_${rowIndex}`);
// console.log('bom ', bom);
if (!bom) {
continue;
}
choiceArr.add(bom);
}
}
console.log('choiceArr ', choiceArr)
}
WfForm.registerCheckEvent(WfForm.OPER_DELROW + "1", function (callback) {
callback();
getBomArr();
initChoiceArr();
});
function getBomArr() {
let arr = [];
let rowArr = WfForm.getDetailAllRowIndexStr('detail_1').split(",");
for (let i = 0; i < rowArr.length; i++) {
let rowIndex = rowArr[i];
if (rowIndex !== "") {
arr.push(WfForm.getFieldValue(`${detailBomField}_${rowIndex}`));
}
}
let bom = new Set(arr);
let arr2 = [...bom];
let obj = {};
obj.value = arr2.join(',');
let specialobjArr = [];
for (let i = 0; i < arr2.length; i++) {
let obj = {};
obj.id = arr2[i];
obj.name = arr2[i];
specialobjArr.push(obj);
}
obj.specialobj = specialobjArr;
let val = WfForm.changeFieldValue(mainAttrField, obj);
if (!val) {
WfForm.delDetailRow("detail_3", "all");
}
console.log('主表辅助字段值 : ', WfForm.getFieldValue(mainAttrField));
}

View File

@ -51,6 +51,9 @@ function init(){
'computeDatePayType': computeDatePayType, 'computeDatePayType': computeDatePayType,
'paymentTypeGetValue': paymentTypeGetValue 'paymentTypeGetValue': paymentTypeGetValue
} }
addRowBack(3, obj);
changeDetailFieldReadOnly(detailTable, detailComPayDateId, detailPaymentTypeId, computeDatePayType) changeDetailFieldReadOnly(detailTable, detailComPayDateId, detailPaymentTypeId, computeDatePayType)
// 主表字段发生变化 // 主表字段发生变化
mainFieldChangeDetailCom(`${mainProjectId},${contractSignDateId}`, detailTable, obj); mainFieldChangeDetailCom(`${mainProjectId},${contractSignDateId}`, detailTable, obj);

View File

@ -52,6 +52,7 @@ function init(){
'computeDatePayType': computeDatePayType, 'computeDatePayType': computeDatePayType,
'paymentTypeGetValue': paymentTypeGetValue 'paymentTypeGetValue': paymentTypeGetValue
} }
addRowBack(2, obj);
changeDetailFieldReadOnly(detailTable, detail2ComPayDateId, detail2PaymentTypeId, computeDatePayType) changeDetailFieldReadOnly(detailTable, detail2ComPayDateId, detail2PaymentTypeId, computeDatePayType)
// 主表字段发生变化 // 主表字段发生变化
mainFieldChangeDetailCom(mainProjectId, detailTable, obj); mainFieldChangeDetailCom(mainProjectId, detailTable, obj);

View File

@ -535,7 +535,46 @@ $(() => {
callback() callback()
}) })
}) })
/* ******************* 流程明细字段包含某个字符串时给某个字段赋值为某个东西end ******************* */
/* ******************* 流程明细字段包含某个字符串时给某个字段赋值为某个东西end ******************* */
/* ******************* 流程提交按钮触发流程抄送start ******************* */
$(() => {
let config = {
// 抄送人所在明细表编号1-明细1 2-明细2
detailNo: '1',
// 抄送人所在字段字段名
ccResourceField: '',
// 一级部门负责人字段名
firstLevelDepResponsibleField: ''
}
WfForm.registerCheckEvent(WfForm.OPER_SUBMIT, function (callback) {
$.ajax("/api/aiyh/pcn/cc-workflow/trigger", {
type: "POST",
data: JSON.stringify({
detailNo: config.detailNo,
requestId: WfForm.getBaseInfo().requestid,
ccResourceField: config.ccResourceField,
firstLevelDepResponsibleField: config.firstLevelDepResponsibleField
}),
headers: {
"Content-Type": "application/json"
},
complete: (res) => {
res.then(r => {
if (r && r.code === 200) {
callback();
}
})
}
})
});
})
/* ******************* 流程提交按钮触发流程抄送end ******************* */
/* ******************* 提交外出流程 ******************* */ /* ******************* 提交外出流程 ******************* */
(function start() { (function start() {

View File

@ -0,0 +1 @@
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCa8TBiSrOPSgJER3nd+gW2eCoSjXHRVxEX54AdxzmtDe4Rn6OlvMVG1GLWfTnjdwbLTVeZUqjTpgZkCdGIp9njgjs6v6oQ7f8+DhQvByp6BSNXBHM+XH+YnmIohcQpnH7qvDT8l41Io2IVZbeNBWMlAtnz7laXWisYkYEDUm8HXOadKLkX+aqWdEYJHGy8zYN9ktNWH7P8BXBUAUd1vtTZhhE6BMd/O0WSqWhgpABbFZ8VKVT/5u4dlXUykKNbCKrsfXoiLE/7plbfHji02sUdaA1LAOF4QOaTePaGZu/55TWCYZPjWKrW2c0Gr8mS/1MQrg1zsWV2c59GqLNMWICtAgMBAAECggEAOS4thvi+j3DmqUAfj3YHybFLBZHBoVoaatH6jALMHDt50nMxt6aUv3D+EN4iEPoKPdkLLQA+Ye1xilW9SEt5s+aJ6UJ2hszuV35moHxqhqGCy0hPJ4KHbFF3NDE5lYm1pPdULqvXbiktt2vUc2y7jBsjSEx7FFwob2azUACKDRL+PkNGGcMmdMeCIHBcQf+j0CTY/VvsPGHqf53I/Ffe2KAE3Y0SugoIB5dqUE9VN5KGC01+X6hufaNUpPLYLbBiaI1eHVtMCHbGNmNnHuFgsEWT4ya4fw1rm9DLS8zJwDHkHmegE5ieqM7EzM2UIvKCN3TQJcy+Ssk3FX+KBFQqmQKBgQDaiC8QFqA7z8DY0K6lwj8PMiuNeu9APJuHLAhGdbDXjAKfdU1cNU4SHfsjjCU4Wymgp8QNrMD8WhardKHV+zr6B0mRMnUYOI6aoAg1+UcGoHYM2PEonZS+OtBHI68wDIsiKQ2Mybsl6GlxoLfo3YdlcclPFHNzXoVc8QFboN0TdwKBgQC1gerb6Anwlj6rJB9RCnoR/Jq5Lyh5wa1eL1C+gZSSM8Mwwxu3VpPohUMca7t1F1vmEDaf/Z2nsQ8IULnYkS94iGYooIcV2ffY5bagi/DkuTYfbf2QBWSZNTI1yHTWoaIXElRG0+svxgL6w98D3Y5lzIt0skz+/ZSGIdiLg8mt+wKBgQCBJCNzxXsxfWeAeWoMKMttJn/YXwLOGkLq0ZmeUeSMrH/MTdzGlfWp/S+xZRuFv1HNT/crAaEWQALPleAhfRLwOKg/9up9wsZ7GAFiLArOHrtEgluZXe5NsKHuuGbJ5U+/gzUvsvM2xq6xaIHmSiu+Rkzpv7MuRXhYYVAlHt4mpwKBgALOOEgf5Q9v8xYIH+fLxqlCg027ed+v67MZ/iCDtj0wSaMWUPZbgzvD246z55jevI/ozj9Y1zgBV58kSEsdq2MskI+uM4hV7yvOGS2QHDAc4MZJl/LC8pQfq2ADcjLjGrNKmDzkB62cXO1tW6Qep5XRPJKYMvJ6DvKn0UYOym5DAoGBALsEOPep1R8CBWCnni8igvbMudBwpzg5e9V6bu7p3MdADhGA/FMkCQgI2VH6fTufQsOA6rYi7YcdMS80r+p1/HMuVskOlqQfPDJ3OG0g0W8nwxf3XbIoEJcaAzLmqDOQMHfhmnoQsPlnCd7YRybbEEkEbKeRjyrDqhMSTSWC8lw4

View File

@ -0,0 +1 @@
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmvEwYkqzj0oCREd53foFtngqEo1x0VcRF+eAHcc5rQ3uEZ+jpbzFRtRi1n0543cGy01XmVKo06YGZAnRiKfZ44I7Or+qEO3/Pg4ULwcqegUjVwRzPlx/mJ5iKIXEKZx+6rw0/JeNSKNiFWW3jQVjJQLZ8+5Wl1orGJGBA1JvB1zmnSi5F/mqlnRGCRxsvM2DfZLTVh+z/AVwVAFHdb7U2YYROgTHfztFkqloYKQAWxWfFSlU/+buHZV1MpCjWwiq7H16IixP+6ZW3x44tNrFHWgNSwDheEDmk3j2hmbv+eU1gmGT41iq1tnNBq/Jkv9TEK4Nc7FldnOfRqizTFiArQIDAQAB

View File

@ -56,6 +56,12 @@
<version>${lombok.version}</version> <version>${lombok.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- 图片efi信息识别ps贵酒-->
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>${metadata-extractor.version}</version>
</dependency>
<!-- 单元测试--> <!-- 单元测试-->

View File

@ -732,7 +732,7 @@ public class Util extends weaver.general.Util {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
for (int i = 0, l = charArray.length; i < l; i++) { for (int i = 0, l = charArray.length; i < l; i++) {
// 判断当前字符是否是"_",如果跳出本次循环 // 判断当前字符是否是"_",如果跳出本次循环
if (charArray[i] == 95) { if (charArray[i] == '_') {
underlineBefore = true; underlineBefore = true;
} else if (underlineBefore) { } else if (underlineBefore) {
// 如果为true代表上次的字符是"_",当前字符需要转成大写 // 如果为true代表上次的字符是"_",当前字符需要转成大写
@ -763,10 +763,10 @@ public class Util extends weaver.general.Util {
for (int i = 0, l = charArray.length; i < l; i++) { for (int i = 0, l = charArray.length; i < l; i++) {
if (charArray[i] >= 65 && charArray[i] <= 90) { if (charArray[i] >= 65 && charArray[i] <= 90) {
if (i == 0) { if (i == 0) {
buffer.append(charArray[i] += 32); buffer.append(Character.toLowerCase(charArray[i]));
continue; continue;
} }
buffer.append("_").append(charArray[i] += 32); buffer.append("_").append(Character.toLowerCase(charArray[i]));
} else { } else {
buffer.append(charArray[i]); buffer.append(charArray[i]);
} }
@ -2100,7 +2100,12 @@ public class Util extends weaver.general.Util {
String s; String s;
for (Iterator<T> item = coll.iterator(); item.hasNext(); sb.append(s)) { for (Iterator<T> item = coll.iterator(); item.hasNext(); sb.append(s)) {
s = (String) item.next(); T value = item.next();
if (Objects.isNull(value)) {
s = "";
} else {
s = String.valueOf(value);
}
if (isFirst) { if (isFirst) {
isFirst = false; isFirst = false;
} else { } else {
@ -2111,6 +2116,38 @@ public class Util extends weaver.general.Util {
} }
} }
/**
* join
*
* @param coll
* @param split
* @return
*/
public static <T> String joinEach(T[] coll, String split) {
if (Objects.isNull(coll)) {
return "";
} else {
StringBuilder sb = new StringBuilder();
boolean isFirst = true;
String s;
for (Iterator<T> item = Arrays.stream(coll).iterator(); item.hasNext(); sb.append(s)) {
T value = item.next();
if (Objects.isNull(value)) {
s = "";
} else {
s = String.valueOf(value);
}
if (isFirst) {
isFirst = false;
} else {
sb.append(split);
}
}
return sb.toString();
}
}
/** /**
* 使 * 使
* *
@ -3736,7 +3773,35 @@ public class Util extends weaver.general.Util {
return Util.getValueByKeyStr("main." + fieldInfo.getFieldName(), workflowData); return Util.getValueByKeyStr("main." + fieldInfo.getFieldName(), workflowData);
} }
public static <K, V> Map<K, V> createFunctionMap() { public static String getIpAddress(HttpServletRequest request) throws IOException {
return null; // 获取请求主机IP地址,如果通过代理进来则透过防火墙获取真实IP地址
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} else if (ip.length() > 15) {
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = ips[index];
if (!("unknown".equalsIgnoreCase(strIp))) {
ip = strIp;
break;
}
}
}
return ip;
} }
} }

View File

@ -18,7 +18,8 @@ public @interface Association {
String column(); String column();
String select();
String select() default "";
Id id(); Id id();

View File

@ -0,0 +1,20 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* <h1></h1>
*
* <p>create: 2022-08-09 17:40</p>
*
* @author aiyh EBU7-dev-1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface BatchDeleteOracle {
String value() default "";
// sql是否是在参数中
boolean custom() default false;
}

View File

@ -0,0 +1,20 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* <h1></h1>
*
* <p>create: 2022-08-09 17:40</p>
*
* @author aiyh EBU7-dev-1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface BatchInsertOracle {
String value() default "";
// sql是否是在参数中
boolean custom() default false;
}

View File

@ -0,0 +1,20 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* <h1></h1>
*
* <p>create: 2022-08-09 17:40</p>
*
* @author aiyh EBU7-dev-1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface BatchUpdateOracle {
String value() default "";
// sql是否是在参数中
boolean custom() default false;
}

View File

@ -0,0 +1,16 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* <h1>null</h1>
*
* <p>create: 2023/3/8 21:41</p>
*
* @author youHong.ai
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface CanBeNull {
}

View File

@ -17,7 +17,7 @@ public @interface CollectionMapping {
String property(); String property();
/** 数据库字段名 */ /** 数据库字段名 */
String column(); String column() default "";
/** 查询方法全限定类名 */ /** 查询方法全限定类名 */
String select() default ""; String select() default "";

View File

@ -0,0 +1,20 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* <h1></h1>
*
* <p>create: 2023/3/10 10:18</p>
*
* @author youHong.ai
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@Documented
public @interface Column {
String value();
String oracle() default "";
}

View File

@ -0,0 +1,18 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* @author @author EBU7-dev1-ay
* create 2021/12/19 0019 15:08
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DeleteOracle {
String value() default "";
// sql是否是在参数中
boolean custom() default false;
}

View File

@ -0,0 +1,18 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* @author @author EBU7-dev1-ay
* create 2021/12/19 0019 15:08
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface InsertOracle {
String value() default "";
// sql是否是在参数中
boolean custom() default false;
}

View File

@ -11,7 +11,8 @@ import java.lang.annotation.*;
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Documented @Documented
public @interface Select { public @interface Select {
String value() default ""; String value() default "";
// sql是否是在参数中
boolean custom() default false; // sql是否是在参数中
boolean custom() default false;
} }

View File

@ -0,0 +1,17 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* @author @author EBU7-dev1-ay
* create 2021/12/19 0019 15:08
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface SelectOracle {
String value() default "";
boolean custom() default false;
}

View File

@ -0,0 +1,18 @@
package aiyh.utils.annotation.recordset;
import java.lang.annotation.*;
/**
* @author @author EBU7-dev1-ay
* create 2021/12/19 0019 15:08
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface UpdateOracle {
String value() default "";
// sql是否是在参数中
boolean custom() default false;
}

View File

@ -1,5 +1,6 @@
package aiyh.utils.entity; package aiyh.utils.entity;
import aiyh.utils.annotation.recordset.SqlOracleDbFieldAnn;
import lombok.Data; import lombok.Data;
/** /**
@ -11,11 +12,33 @@ import lombok.Data;
@Data @Data
public class DocImageInfo { public class DocImageInfo {
/** docId */
@SqlOracleDbFieldAnn("DOC_ID")
private Integer docId; private Integer docId;
/** image id */
@SqlOracleDbFieldAnn("IMAGE_FILE_ID")
private Integer imageFileId; private Integer imageFileId;
/** 文件名称 */
@SqlOracleDbFieldAnn("IMAGE_FILE_NAME")
private String imageFileName; private String imageFileName;
/** 创建时间 */
@SqlOracleDbFieldAnn("DOC_CREATE_TIME")
private String docCreateTime;
/** 创建日期 */
@SqlOracleDbFieldAnn("DOC_CREATE_DATE")
private String docCreateDate;
/** 明细数据id */
@SqlOracleDbFieldAnn("ID")
private Integer id; private Integer id;
/** 其他id */
@SqlOracleDbFieldAnn("DETAIL_ID")
private Integer detailId; private Integer detailId;
/** 文件大小 */
@SqlOracleDbFieldAnn("FILE_SIZE")
private Integer fileSize; private Integer fileSize;
/** 文件类型 */
@SqlOracleDbFieldAnn("DOC_FILE_TYPE")
private Integer docFileType; private Integer docFileType;
} }

View File

@ -6,7 +6,7 @@ import lombok.Setter;
import lombok.ToString; import lombok.ToString;
/** /**
* <h1></h1> * <h1></h1>
* *
* <p>create: 2023/2/20 11:01</p> * <p>create: 2023/2/20 11:01</p>
* *

View File

@ -0,0 +1,28 @@
package aiyh.utils.entity;
import aiyh.utils.annotation.recordset.SqlOracleDbFieldAnn;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* <h1></h1>
*
* <p>create: 2023/3/14 17:05</p>
*
* @author youHong.ai
*/
@Getter
@Setter
@ToString
public class ModelTableInfo {
/** id */
@SqlOracleDbFieldAnn("ID")
private String id;
@SqlOracleDbFieldAnn("INDEX_DESC")
private String indexDesc;
/** 字段表名 */
@SqlOracleDbFieldAnn("TABLE_NAME")
private String tableName;
}

View File

@ -3,7 +3,7 @@ package aiyh.utils.entity;
import lombok.Data; import lombok.Data;
/** /**
* <p></p> * <p></p>
* <p>create 2022/6/10 21:21</p> * <p>create 2022/6/10 21:21</p>
* *
* @author ayh * @author ayh
@ -11,10 +11,10 @@ import lombok.Data;
@Data @Data
public class SelectValueEntity { public class SelectValueEntity {
private String id; private String id;
private String fieldname; private String fieldname;
private String fieldlabel; private String fieldlabel;
private String tablename; private String tablename;
private String selectname; private String selectname;
private Integer selectvalue; private Integer selectvalue;
} }

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,6 @@ import weaver.file.ImageFileManager;
import weaver.system.SystemComInfo; import weaver.system.SystemComInfo;
import java.io.*; import java.io.*;
import java.net.URLDecoder;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List; import java.util.List;
@ -30,216 +29,216 @@ import java.util.UUID;
public class PdfUtil { public class PdfUtil {
private static final Logger log = Util.getLogger("util_water_log"); private static final Logger log = Util.getLogger("util_water_log");
/** /**
* *
* *
* @param inputStream pdf * @param inputStream pdf
* @param keyword * @param keyword
* @return * @return
*/ */
public static List<PdfPointItem> findKeywordPoints(InputStream inputStream, String keyword) { public static List<PdfPointItem> findKeywordPoints(InputStream inputStream, String keyword) {
PdfReader pdfReader = null; PdfReader pdfReader = null;
try { try {
pdfReader = new PdfReader(inputStream); pdfReader = new PdfReader(inputStream);
} catch (IOException e) { } catch (IOException e) {
throw new CustomerException("读取pdf失败", e); throw new CustomerException("读取pdf失败", e);
} }
return getKeywordPoints(pdfReader, keyword); return getKeywordPoints(pdfReader, keyword);
} }
/** /**
* *
* *
* @param pdfReader pdf * @param pdfReader pdf
* @param keyword * @param keyword
* @return * @return
*/ */
private static List<PdfPointItem> getKeywordPoints(PdfReader pdfReader, String keyword) { private static List<PdfPointItem> getKeywordPoints(PdfReader pdfReader, String keyword) {
int totalPage = pdfReader.getNumberOfPages(); int totalPage = pdfReader.getNumberOfPages();
PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader); PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);
CustomerPdfRenderListener customerPdfRenderListener = new CustomerPdfRenderListener(); CustomerPdfRenderListener customerPdfRenderListener = new CustomerPdfRenderListener();
customerPdfRenderListener.setKeyWord(keyword); customerPdfRenderListener.setKeyWord(keyword);
customerPdfRenderListener.setTotalPage(totalPage); customerPdfRenderListener.setTotalPage(totalPage);
for (int page = 1; page <= totalPage; page++) { for (int page = 1; page <= totalPage; page++) {
customerPdfRenderListener.setPage(page); customerPdfRenderListener.setPage(page);
try { try {
pdfReaderContentParser.processContent(page, customerPdfRenderListener); pdfReaderContentParser.processContent(page, customerPdfRenderListener);
} catch (IOException e) { } catch (IOException e) {
throw new CustomerException("解析pdf失败", e); throw new CustomerException("解析pdf失败", e);
} }
} }
pdfReader.close(); pdfReader.close();
return customerPdfRenderListener.getPoints(); return customerPdfRenderListener.getPoints();
} }
/** /**
* *
* *
* @param pdfImageFileId pdfid * @param pdfImageFileId pdfid
* @param pictureInputStream * @param pictureInputStream
* @param keyword * @param keyword
* @param allKeyword * @param allKeyword
* @param opacity * @param opacity
* @param imageFitWidth * @param imageFitWidth
* @param imageFitHeight * @param imageFitHeight
* @param offsetX x * @param offsetX x
* @param offsetY y * @param offsetY y
* @return pdf * @return pdf
*/ */
public static int addPictureWater2pdfByKeyword(int pdfImageFileId, public static int addPictureWater2pdfByKeyword(int pdfImageFileId,
InputStream pictureInputStream, InputStream pictureInputStream,
String keyword, String keyword,
boolean allKeyword, boolean allKeyword,
float opacity, float opacity,
int imageFitWidth, int imageFitWidth,
int imageFitHeight, int imageFitHeight,
int offsetX, int offsetX,
int offsetY) { int offsetY) {
ImageFileManager imageFileManager = new ImageFileManager(); ImageFileManager imageFileManager = new ImageFileManager();
imageFileManager.getImageFileInfoById(pdfImageFileId); imageFileManager.getImageFileInfoById(pdfImageFileId);
String imageFileName = imageFileManager.getImageFileName(); String imageFileName = imageFileManager.getImageFileName();
String suffix = imageFileName.substring(imageFileName.lastIndexOf(".") + 1); String suffix = imageFileName.substring(imageFileName.lastIndexOf(".") + 1);
if (!"pdf".equalsIgnoreCase(suffix)) { if (!"pdf".equalsIgnoreCase(suffix)) {
throw new CustomerException("不支持的文件类型 " + suffix); throw new CustomerException("不支持的文件类型 " + suffix);
} }
InputStream inputStream = ImageFileManager.getInputStreamById(pdfImageFileId); InputStream inputStream = ImageFileManager.getInputStreamById(pdfImageFileId);
List<PdfPointItem> keywordPoints = findKeywordPoints(inputStream, keyword); List<PdfPointItem> keywordPoints = findKeywordPoints(inputStream, keyword);
PdfReader pdfReader = null; PdfReader pdfReader = null;
Image image = null; Image image = null;
try { try {
byte[] imgb = org.apache.commons.io.IOUtils.toByteArray(pictureInputStream); byte[] imgb = org.apache.commons.io.IOUtils.toByteArray(pictureInputStream);
image = Image.getInstance(imgb); image = Image.getInstance(imgb);
} catch (Exception e) { } catch (Exception e) {
throw new CustomerException("获取水印图片失败!", e); throw new CustomerException("获取水印图片失败!", e);
} }
PdfGState gs = new PdfGState(); PdfGState gs = new PdfGState();
gs.setFillOpacity(opacity); gs.setFillOpacity(opacity);
image.scaleToFit(imageFitWidth, imageFitHeight); image.scaleToFit(imageFitWidth, imageFitHeight);
String createDir = FileUpload.getCreateDir(new SystemComInfo().getFilesystem()) + "tempfile" + File.separator; String createDir = FileUpload.getCreateDir(new SystemComInfo().getFilesystem()) + "tempfile" + File.separator;
// 防止高并发下文件名重复导致文件覆盖的问题 // 防止高并发下文件名重复导致文件覆盖的问题
String tempPath = createDir + imageFileName + System.currentTimeMillis() + UUID.randomUUID() + ".pdf"; String tempPath = createDir + imageFileName + System.currentTimeMillis() + UUID.randomUUID() + ".pdf";
File file = new File(tempPath); File file = new File(tempPath);
if (!file.getParentFile().exists()) { if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
} }
if (!file.exists()) { if (!file.exists()) {
try { try {
file.createNewFile(); file.createNewFile();
} catch (IOException e) { } catch (IOException e) {
throw new CustomerException("创建临时文件失败!", e); throw new CustomerException("创建临时文件失败!", e);
} }
} }
// 输出到临时目录 // 输出到临时目录
FileOutputStream outputStreamTem; FileOutputStream outputStreamTem;
try { try {
outputStreamTem = new FileOutputStream(URLDecoder.decode(tempPath, "utf-8")); outputStreamTem = new FileOutputStream(tempPath);
} catch (FileNotFoundException | UnsupportedEncodingException e) { } catch (FileNotFoundException e) {
throw new CustomerException("创建临时文件流和路径转换失败!", e); throw new CustomerException("创建临时文件流和路径转换失败!", e);
} }
PdfStamper pdfStamper = null; PdfStamper pdfStamper = null;
try { try {
inputStream = ImageFileManager.getInputStreamById(pdfImageFileId); inputStream = ImageFileManager.getInputStreamById(pdfImageFileId);
pdfReader = new PdfReader(inputStream); pdfReader = new PdfReader(inputStream);
pdfStamper = new PdfStamper(pdfReader, outputStreamTem); pdfStamper = new PdfStamper(pdfReader, outputStreamTem);
} catch (IOException | DocumentException e) { } catch (IOException | DocumentException e) {
throw new CustomerException("读取pdf失败", e); throw new CustomerException("读取pdf失败", e);
} }
if (allKeyword) { if (allKeyword) {
addPictureWater2pdfByKeywordAllKeyword(pdfStamper, keywordPoints, image, gs, offsetX, offsetY); addPictureWater2pdfByKeywordAllKeyword(pdfStamper, keywordPoints, image, gs, offsetX, offsetY);
} else { } else {
PdfPointItem keywordPoint = keywordPoints.get(0); PdfPointItem keywordPoint = keywordPoints.get(0);
PdfContentByte overContent = pdfStamper.getOverContent(keywordPoint.getStartPage()); PdfContentByte overContent = pdfStamper.getOverContent(keywordPoint.getStartPage());
overContent.setGState(gs); overContent.setGState(gs);
float absoluteX = keywordPoint.getStartPointX() + offsetX; float absoluteX = keywordPoint.getStartPointX() + offsetX;
float absoluteY = keywordPoint.getStartPointY() + offsetY; float absoluteY = keywordPoint.getStartPointY() + offsetY;
image.setAbsolutePosition(absoluteX, absoluteY); image.setAbsolutePosition(absoluteX, absoluteY);
try { try {
overContent.addImage(image); overContent.addImage(image);
} catch (DocumentException e) { } catch (DocumentException e) {
throw new CustomerException("添加水印图片失败!", e); throw new CustomerException("添加水印图片失败!", e);
} }
} }
try { try {
pdfStamper.close(); pdfStamper.close();
outputStreamTem.close(); outputStreamTem.close();
} catch (IOException | DocumentException e) { } catch (IOException | DocumentException e) {
e.printStackTrace(); e.printStackTrace();
log.error("关闭流失败!", e); log.error("关闭流失败!", e);
} }
int imageFileId = -1; int imageFileId = -1;
InputStream waterPdf = null; InputStream waterPdf = null;
try { try {
waterPdf = new FileInputStream(tempPath); waterPdf = new FileInputStream(tempPath);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
throw new CustomerException("文件水印添加失败!", e); throw new CustomerException("文件水印添加失败!", e);
} }
imageFileId = Util.createFileByInputSteam(waterPdf, imageFileName); imageFileId = Util.createFileByInputSteam(waterPdf, imageFileName);
try { try {
waterPdf.close(); waterPdf.close();
Files.deleteIfExists(Paths.get(tempPath)); Files.deleteIfExists(Paths.get(tempPath));
} catch (IOException e ){ } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
return imageFileId; return imageFileId;
} }
/** /**
* *
* *
* @param pdfImageFileId pdfid * @param pdfImageFileId pdfid
* @param pictureImageFileId id * @param pictureImageFileId id
* @param keyword * @param keyword
* @param allKeyword * @param allKeyword
* @param opacity * @param opacity
* @param imageFitWidth * @param imageFitWidth
* @param imageFitHeight * @param imageFitHeight
* @param offsetX x * @param offsetX x
* @param offsetY y * @param offsetY y
* @return pdf * @return pdf
*/ */
public static int addPictureWater2pdfByKeyword(int pdfImageFileId, public static int addPictureWater2pdfByKeyword(int pdfImageFileId,
int pictureImageFileId, int pictureImageFileId,
String keyword, String keyword,
boolean allKeyword, boolean allKeyword,
float opacity, float opacity,
int imageFitWidth, int imageFitWidth,
int imageFitHeight, int imageFitHeight,
int offsetX, int offsetX,
int offsetY) { int offsetY) {
InputStream pictureInputStream = ImageFileManager.getInputStreamById(pictureImageFileId); InputStream pictureInputStream = ImageFileManager.getInputStreamById(pictureImageFileId);
return addPictureWater2pdfByKeyword(pdfImageFileId, pictureInputStream, keyword, allKeyword, opacity, imageFitWidth, imageFitHeight, offsetX, offsetY); return addPictureWater2pdfByKeyword(pdfImageFileId, pictureInputStream, keyword, allKeyword, opacity, imageFitWidth, imageFitHeight, offsetX, offsetY);
} }
/** /**
* *
* *
* @param pdfStamper pdfStamper * @param pdfStamper pdfStamper
* @param keywordPoints * @param keywordPoints
* @param image * @param image
* @param gs * @param gs
* @param offsetX X * @param offsetX X
* @param offsetY Y * @param offsetY Y
*/ */
private static void addPictureWater2pdfByKeywordAllKeyword(PdfStamper pdfStamper, private static void addPictureWater2pdfByKeywordAllKeyword(PdfStamper pdfStamper,
List<PdfPointItem> keywordPoints, List<PdfPointItem> keywordPoints,
Image image, PdfGState gs, Image image, PdfGState gs,
int offsetX, int offsetY) { int offsetX, int offsetY) {
PdfContentByte overContent = null; PdfContentByte overContent = null;
for (PdfPointItem keywordPoint : keywordPoints) { for (PdfPointItem keywordPoint : keywordPoints) {
overContent = pdfStamper.getOverContent(keywordPoint.getStartPage()); overContent = pdfStamper.getOverContent(keywordPoint.getStartPage());
overContent.setGState(gs); overContent.setGState(gs);
float absoluteX = keywordPoint.getStartPointX() + offsetX; float absoluteX = keywordPoint.getStartPointX() + offsetX;
float absoluteY = keywordPoint.getStartPointY() + offsetY; float absoluteY = keywordPoint.getStartPointY() + offsetY;
image.setAbsolutePosition(absoluteX, absoluteY); image.setAbsolutePosition(absoluteX, absoluteY);
try { try {
overContent.addImage(image); overContent.addImage(image);
} catch (DocumentException e) { } catch (DocumentException e) {
throw new CustomerException("添加水印图片失败!", e); throw new CustomerException("添加水印图片失败!", e);
} }
} }
} }
} }

View File

@ -4,7 +4,6 @@ package aiyh.utils.httpUtil;
import aiyh.utils.Util; import aiyh.utils.Util;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -136,11 +135,11 @@ public class ResponeVo implements HttpResponse {
} catch (JsonProcessingException ignored) { } catch (JsonProcessingException ignored) {
try { try {
this.resultList = (List<Map>) JSONArray.parseArray(this.getEntityString(), Map.class); this.resultList = (List<Map>) JSONArray.parseArray(this.getEntityString(), Map.class);
} catch (JSONException e) { } catch (Exception e) {
Util.getLogger().error("Unable to convert the response result to array" + Util.getErrString(e)); Util.getLogger().error("Unable to convert the response result to array");
} }
} catch (Exception e) { } catch (Exception e) {
Util.getLogger().error("Unable to convert the response result to map or array" + Util.getErrString(e)); Util.getLogger().error("Unable to convert the response result to map or array");
} }
} }

View File

@ -86,6 +86,10 @@ public class HttpUtils {
} }
public void setCredentialsProvider(CredentialsProvider credentialsProvider) {
this.credentialsProvider = credentialsProvider;
}
public HttpUtils(CredentialsProvider credentialsProvider) { public HttpUtils(CredentialsProvider credentialsProvider) {
this.credentialsProvider = credentialsProvider; this.credentialsProvider = credentialsProvider;
} }

View File

@ -1,10 +1,7 @@
package aiyh.utils.mapper; package aiyh.utils.mapper;
import aiyh.utils.annotation.recordset.*; import aiyh.utils.annotation.recordset.*;
import aiyh.utils.entity.DocImageInfo; import aiyh.utils.entity.*;
import aiyh.utils.entity.FieldViewInfo;
import aiyh.utils.entity.SelectValueEntity;
import aiyh.utils.entity.WorkflowNodeConfig;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -58,17 +55,31 @@ public interface UtilMapper {
String selectWorkfowMainTable(@ParamMapper("workflowId") String workflowId); String selectWorkfowMainTable(@ParamMapper("workflowId") String workflowId);
@Select("select id,docid doc_id,imagefileid image_file_id,imagefilename image_file_name from docimagefile where docid = #{docId}") @Select("select di.id id,dc.id doc_id," +
"di.imagefileid image_file_id," +
"dc.DOCCREATEDATE doc_create_date,dc.DOCCREATETIME doc_create_time," +
"(case when imagefilename = '' or imagefilename is null then dc.DOCSUBJECT else imagefilename end) image_file_name " +
"from DocDetail dc " +
"left join docimagefile di on (dc.id = #{docId} and dc.id = di.docid) " +
"where dc.id = #{docId} ")
DocImageInfo selectDocImageInfo(@ParamMapper("docId") String docId); DocImageInfo selectDocImageInfo(@ParamMapper("docId") String docId);
@Select("select id,docid doc_id," + @Select("select di.id id,dc.id doc_id," +
"imagefileid image_file_id, docfiletype doc_file_type," + "di.imagefileid image_file_id, di.docfiletype doc_file_type," +
"imagefilename image_file_name from docimagefile where docid in ($t{docIds})") "dc.DOCCREATEDATE doc_create_date,dc.DOCCREATETIME doc_create_time," +
"(case when imagefilename = '' or imagefilename is null then dc.DOCSUBJECT else imagefilename end) image_file_name " +
"from DocDetail dc " +
"left join docimagefile di on (dc.id in ($t{docIds}) and dc.id = di.docid )" +
"where dc.id in ($t{docIds})")
List<DocImageInfo> selectDocImageInfos(@ParamMapper("docIds") String docIds); List<DocImageInfo> selectDocImageInfos(@ParamMapper("docIds") String docIds);
@Select("select id,docid doc_id,imagefileid image_file_id," + @Select("select di.id id,dc.id doc_id," +
"docfiletype doc_file_type," + "di.imagefileid image_file_id, di.docfiletype doc_file_type," +
"imagefilename image_file_name from docimagefile where docid in (${docIds})") "dc.DOCCREATEDATE doc_create_date,dc.DOCCREATETIME doc_create_time," +
"(case when imagefilename = '' or imagefilename is null then dc.DOCSUBJECT else imagefilename end) image_file_name " +
"from DocDetail dc " +
"left join docimagefile di on (dc.id in ($t{docIds}) and dc.id = di.docid )" +
"where dc.id in ($t{docIds})")
List<DocImageInfo> selectDocImageInfos(@ParamMapper("docIds") String[] docIds); List<DocImageInfo> selectDocImageInfos(@ParamMapper("docIds") String[] docIds);
@ -176,4 +187,14 @@ public interface UtilMapper {
" fieldhtmltype field_html_type\n" + " fieldhtmltype field_html_type\n" +
"from workflow_field_table_view where id = #{id}") "from workflow_field_table_view where id = #{id}")
FieldViewInfo selectFieldInfo(Integer id); FieldViewInfo selectFieldInfo(Integer id);
/**
* <h2></h2>
*
* @param id id
* @return
*/
@Select("select id, tablename table_name, indexdesc index_desc from mode_bill_info_view where id = #{id}")
ModelTableInfo selectModelTableInfo(Integer id);
} }

View File

@ -1,10 +1,12 @@
package aiyh.utils.recordset; package aiyh.utils.recordset;
import aiyh.utils.Util; import aiyh.utils.Util;
import aiyh.utils.annotation.recordset.CanBeNull;
import weaver.conn.RecordSet; import weaver.conn.RecordSet;
import weaver.conn.RecordSetTrans; import weaver.conn.RecordSetTrans;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Objects;
/** /**
* <p>float</p> * <p>float</p>
@ -18,7 +20,12 @@ public class DoubleTypeHandler implements TypeHandler {
public Object getValue(RecordSet rs, String fieldName, Field declaredField) { public Object getValue(RecordSet rs, String fieldName, Field declaredField) {
String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField)); String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0D;
} }
return Double.parseDouble(string); return Double.parseDouble(string);
} }
@ -27,7 +34,12 @@ public class DoubleTypeHandler implements TypeHandler {
public Object getValue(RecordSet rs, int index, Field declaredField) { public Object getValue(RecordSet rs, int index, Field declaredField) {
String string = Util.null2String(rs.getString(index)); String string = Util.null2String(rs.getString(index));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0D;
} }
return Double.parseDouble(string); return Double.parseDouble(string);
} }
@ -36,7 +48,12 @@ public class DoubleTypeHandler implements TypeHandler {
public Object getValue(RecordSetTrans rs, String fieldName, Field declaredField) { public Object getValue(RecordSetTrans rs, String fieldName, Field declaredField) {
String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField)); String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0D;
} }
return Double.parseDouble(string); return Double.parseDouble(string);
} }
@ -45,7 +62,12 @@ public class DoubleTypeHandler implements TypeHandler {
public Object getValue(RecordSetTrans rs, int index, Field declaredField) { public Object getValue(RecordSetTrans rs, int index, Field declaredField) {
String string = Util.null2String(rs.getString(index)); String string = Util.null2String(rs.getString(index));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0D;
} }
return Double.parseDouble(string); return Double.parseDouble(string);
} }

View File

@ -1,10 +1,12 @@
package aiyh.utils.recordset; package aiyh.utils.recordset;
import aiyh.utils.Util; import aiyh.utils.Util;
import aiyh.utils.annotation.recordset.CanBeNull;
import weaver.conn.RecordSet; import weaver.conn.RecordSet;
import weaver.conn.RecordSetTrans; import weaver.conn.RecordSetTrans;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Objects;
/** /**
* <p>float</p> * <p>float</p>
@ -18,7 +20,12 @@ public class FloatTypeHandler implements TypeHandler {
public Object getValue(RecordSet rs, String fieldName, Field declaredField) { public Object getValue(RecordSet rs, String fieldName, Field declaredField) {
String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField)); String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0F;
} }
return Float.parseFloat(string); return Float.parseFloat(string);
} }
@ -27,7 +34,12 @@ public class FloatTypeHandler implements TypeHandler {
public Object getValue(RecordSet rs, int index, Field declaredField) { public Object getValue(RecordSet rs, int index, Field declaredField) {
String string = Util.null2String(rs.getString(index), "0.0"); String string = Util.null2String(rs.getString(index), "0.0");
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0F;
} }
return Float.parseFloat(string); return Float.parseFloat(string);
} }
@ -36,7 +48,12 @@ public class FloatTypeHandler implements TypeHandler {
public Object getValue(RecordSetTrans rs, String fieldName, Field declaredField) { public Object getValue(RecordSetTrans rs, String fieldName, Field declaredField) {
String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField)); String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0F;
} }
return Float.parseFloat(string); return Float.parseFloat(string);
} }
@ -45,7 +62,12 @@ public class FloatTypeHandler implements TypeHandler {
public Object getValue(RecordSetTrans rs, int index, Field declaredField) { public Object getValue(RecordSetTrans rs, int index, Field declaredField) {
String string = Util.null2String(rs.getString(index)); String string = Util.null2String(rs.getString(index));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return 0.0F;
} }
return Float.parseFloat(string); return Float.parseFloat(string);
} }

View File

@ -0,0 +1,38 @@
package aiyh.utils.recordset;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.parser.ParserException;
import weaver.conn.RecordSet;
import java.util.Objects;
/**
* <h1>sql</h1>
*
* <p>create: 2023/3/5 11:45</p>
*
* @author youHong.ai
*/
public class FormatSqlUtil {
private static String dbType = null;
private static RecordSet recordSet = null;
public static String formatSql(String sql) {
if (Objects.isNull(FormatSqlUtil.dbType)) {
if (recordSet == null) {
recordSet = new RecordSet();
}
FormatSqlUtil.dbType = recordSet.getDBType();
}
try {
return SQLUtils.format(sql, dbType);
} catch (ParserException e) {
return toSqlString(sql);
}
}
private static String toSqlString(String sql) {
return sql;
}
}

View File

@ -1,10 +1,12 @@
package aiyh.utils.recordset; package aiyh.utils.recordset;
import aiyh.utils.Util; import aiyh.utils.Util;
import aiyh.utils.annotation.recordset.CanBeNull;
import weaver.conn.RecordSet; import weaver.conn.RecordSet;
import weaver.conn.RecordSetTrans; import weaver.conn.RecordSetTrans;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Objects;
/** /**
* @author EBU7-dev1-ayh create 2021/12/21 0021 13:10 * @author EBU7-dev1-ayh create 2021/12/21 0021 13:10
@ -16,7 +18,10 @@ public class IntegerTypeHandler implements TypeHandler {
public Object getValue(RecordSet rs, String fieldName, Field declaredField) { public Object getValue(RecordSet rs, String fieldName, Field declaredField) {
String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField)); String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
return -1;
} }
if (string.contains(".")) { if (string.contains(".")) {
string = string.substring(0, string.indexOf(".")); string = string.substring(0, string.indexOf("."));
@ -28,7 +33,12 @@ public class IntegerTypeHandler implements TypeHandler {
public Object getValue(RecordSet rs, int index, Field declaredField) { public Object getValue(RecordSet rs, int index, Field declaredField) {
String string = Util.null2String(rs.getString(index)); String string = Util.null2String(rs.getString(index));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return -1;
} }
if (string.contains(".")) { if (string.contains(".")) {
string = string.substring(0, string.indexOf(".")); string = string.substring(0, string.indexOf("."));
@ -40,7 +50,12 @@ public class IntegerTypeHandler implements TypeHandler {
public Object getValue(RecordSetTrans rs, String fieldName, Field declaredField) { public Object getValue(RecordSetTrans rs, String fieldName, Field declaredField) {
String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField)); String string = Util.null2String(GetRsValueUtil.getRsValue(rs, fieldName, declaredField));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return -1;
} }
if (string.contains(".")) { if (string.contains(".")) {
string = string.substring(0, string.indexOf(".")); string = string.substring(0, string.indexOf("."));
@ -52,7 +67,12 @@ public class IntegerTypeHandler implements TypeHandler {
public Object getValue(RecordSetTrans rs, int index, Field declaredField) { public Object getValue(RecordSetTrans rs, int index, Field declaredField) {
String string = Util.null2String(rs.getString(index)); String string = Util.null2String(rs.getString(index));
if ("".equals(string)) { if ("".equals(string)) {
return null; if (!Objects.isNull(declaredField)) {
if (declaredField.isAnnotationPresent(CanBeNull.class)) {
return null;
}
}
return -1;
} }
if (string.contains(".")) { if (string.contains(".")) {
string = string.substring(0, string.indexOf(".")); string = string.substring(0, string.indexOf("."));

View File

@ -8,6 +8,7 @@ import aiyh.utils.sqlUtil.sqlResult.impl.BatchSqlResultImpl;
import aiyh.utils.sqlUtil.sqlResult.impl.PrepSqlResultImpl; import aiyh.utils.sqlUtil.sqlResult.impl.PrepSqlResultImpl;
import weaver.conn.RecordSet; import weaver.conn.RecordSet;
import weaver.conn.RecordSetTrans; import weaver.conn.RecordSetTrans;
import weaver.conn.constant.DBConstant;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -59,6 +60,146 @@ public class RecordsetUtil implements InvocationHandler {
return invokeRsTrans(proxy, method, args, name); return invokeRsTrans(proxy, method, args, name);
} }
private Object invokeDefault(int type, String sql, boolean custom, RecordSet rs, Method method, Object[] args) {
SqlHandler sqlHandler = new SqlHandler();
ResultMapper resultMapper = new ResultMapper();
PrepSqlResultImpl handler = sqlHandler.handler(sql, custom, method, args);
String invokeMethod = method.getDeclaringClass().getName() + ":" + method.getName() + " : ";
switch (type) {
case 1: {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("select ")) {
throw new CustomerException("The sql statement does not match, the @Select annotation can only execute the select statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info(invokeMethod + handler);
if (handler.getArgs().isEmpty()) {
rs.executeQuery(handler.getSqlStr());
} else {
rs.executeQuery(handler.getSqlStr(), handler.getArgs());
}
return resultMapper.mapperResult(rs, method, method.getReturnType(), this);
}
case 2: {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("update ")) {
throw new CustomerException("The sql statement does not match, the @Update annotation can only execute the update statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info(invokeMethod + handler);
Class<?> returnType = method.getReturnType();
boolean b;
if (handler.getArgs().isEmpty()) {
b = rs.executeUpdate(handler.getSqlStr());
} else {
b = rs.executeUpdate(handler.getSqlStr(), handler.getArgs());
}
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(int.class) || returnType.equals(Integer.class)) {
if (b) {
return 1;
} else {
return 0;
}
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
}
case 3: {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("insert ")) {
throw new CustomerException("The sql statement does not match, the @Insert annotation can only execute the insert statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info(invokeMethod + handler);
Class<?> returnType = method.getReturnType();
boolean b;
if (handler.getArgs().isEmpty()) {
b = rs.executeUpdate(handler.getSqlStr());
} else {
b = rs.executeUpdate(handler.getSqlStr(), handler.getArgs());
}
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
}
case 4: {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("delete ")) {
throw new CustomerException("The sql statement does not match, the @Delete annotation can only execute the delete statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info(invokeMethod + handler);
Class<?> returnType = method.getReturnType();
boolean b;
if (handler.getArgs().isEmpty()) {
b = rs.executeUpdate(handler.getSqlStr());
} else {
b = rs.executeUpdate(handler.getSqlStr(), handler.getArgs());
}
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
}
case 5: {
Class<?> returnType = method.getReturnType();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args);
Util.getLogger(SQL_LOG).info(invokeMethod + batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!");
}
if (!batchSqlResult.getSqlStr().trim().toLowerCase().startsWith("insert ")) {
throw new CustomerException("The sql statement does not match, the @Insert annotation can only execute the insert statement, please check whether the sql statement matches!");
}
boolean b = rs.executeBatchSql(batchSqlResult.getSqlStr(), batchSqlResult.getBatchList());
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
}
case 6: {
Class<?> returnType = method.getReturnType();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args);
Util.getLogger(SQL_LOG).info(invokeMethod + batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!");
}
if (!batchSqlResult.getSqlStr().trim().toLowerCase().startsWith("update ")) {
throw new CustomerException("The sql statement does not match, the @Update annotation can only execute the update statement, please check whether the sql statement matches!");
}
boolean b = rs.executeBatchSql(batchSqlResult.getSqlStr(), batchSqlResult.getBatchList());
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
}
case 7: {
Class<?> returnType = method.getReturnType();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args);
Util.getLogger(SQL_LOG).info(invokeMethod + batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!");
}
if (!batchSqlResult.getSqlStr().trim().toLowerCase().startsWith("delete ")) {
throw new CustomerException("The sql statement does not match, the @Delete annotation can only execute the delete statement, please check whether the sql statement matches!");
}
boolean b = rs.executeBatchSql(batchSqlResult.getSqlStr(), batchSqlResult.getBatchList());
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
}
default:
throw new CustomerException("不支持的sql注解类型 " + type);
}
}
private Object invokeRs(Object proxy, Method method, Object[] args, String name) { private Object invokeRs(Object proxy, Method method, Object[] args, String name) {
String mapperKey = method.getDeclaringClass().getName(); String mapperKey = method.getDeclaringClass().getName();
@ -71,177 +212,100 @@ public class RecordsetUtil implements InvocationHandler {
rs = rsManager.getRs(mapperKey); rs = rsManager.getRs(mapperKey);
} }
SqlHandler sqlHandler = new SqlHandler(); SqlHandler sqlHandler = new SqlHandler();
ResultMapper resultMapper = new ResultMapper(); if (DBConstant.DB_TYPE_ORACLE.equals(rs.getDBType())) {
SelectOracle selectOracle = method.getAnnotation(SelectOracle.class);
if (selectOracle != null) {
String sql = selectOracle.value();
boolean custom = selectOracle.custom();
return invokeDefault(1, sql, custom, rs, method, args);
}
UpdateOracle updateOracle = method.getAnnotation(UpdateOracle.class);
if (updateOracle != null) {
String sql = updateOracle.value();
boolean custom = updateOracle.custom();
return invokeDefault(2, sql, custom, rs, method, args);
}
InsertOracle insertOracle = method.getAnnotation(InsertOracle.class);
if (insertOracle != null) {
String sql = insertOracle.value();
boolean custom = insertOracle.custom();
return invokeDefault(3, sql, custom, rs, method, args);
}
DeleteOracle deleteOracle = method.getAnnotation(DeleteOracle.class);
if (deleteOracle != null) {
String sql = deleteOracle.value();
boolean custom = deleteOracle.custom();
return invokeDefault(4, sql, custom, rs, method, args);
}
BatchInsertOracle batchInsertOracle = method.getAnnotation(BatchInsertOracle.class);
if (batchInsertOracle != null) {
String sql = batchInsertOracle.value();
boolean custom = batchInsertOracle.custom();
return invokeDefault(5, sql, custom, rs, method, args);
}
BatchUpdateOracle batchUpdateOracle = method.getAnnotation(BatchUpdateOracle.class);
if (batchUpdateOracle != null) {
String sql = batchUpdateOracle.value();
boolean custom = batchUpdateOracle.custom();
return invokeDefault(6, sql, custom, rs, method, args);
}
BatchDeleteOracle batchDeleteOracle = method.getAnnotation(BatchDeleteOracle.class);
if (batchDeleteOracle != null) {
String sql = batchDeleteOracle.value();
boolean custom = batchDeleteOracle.custom();
return invokeDefault(7, sql, custom, rs, method, args);
}
}
Select select = method.getAnnotation(Select.class); Select select = method.getAnnotation(Select.class);
if (select != null) { if (select != null) {
// 查询
String sql = select.value(); String sql = select.value();
boolean custom = select.custom(); boolean custom = select.custom();
PrepSqlResultImpl handler = sqlHandler.handler(sql, custom, method, args); return invokeDefault(1, sql, custom, rs, method, args);
if (!handler.getSqlStr().trim().toLowerCase().startsWith("select ")) {
throw new CustomerException("The sql statement does not match, the @Select annotation can only execute the select statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info("解析sql===>" + handler);
if (handler.getArgs().isEmpty()) {
rs.executeQuery(handler.getSqlStr());
} else {
rs.executeQuery(handler.getSqlStr(), handler.getArgs());
}
return resultMapper.mapperResult(rs, method, method.getReturnType(), this);
} }
Update update = method.getAnnotation(Update.class); Update update = method.getAnnotation(Update.class);
if (update != null) { if (update != null) {
// 查询
String sql = update.value(); String sql = update.value();
boolean custom = update.custom(); boolean custom = update.custom();
PrepSqlResultImpl handler = sqlHandler.handler(sql, custom, method, args); return invokeDefault(2, sql, custom, rs, method, args);
if (!handler.getSqlStr().trim().toLowerCase().startsWith("update ")) {
throw new CustomerException("The sql statement does not match, the @Update annotation can only execute the update statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info(handler.toString());
Class<?> returnType = method.getReturnType();
boolean b;
if (handler.getArgs().isEmpty()) {
b = rs.executeUpdate(handler.getSqlStr());
} else {
b = rs.executeUpdate(handler.getSqlStr(), handler.getArgs());
}
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(int.class) || returnType.equals(Integer.class)) {
if (b) {
return 1;
} else {
return 0;
}
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
} }
Insert insert = method.getAnnotation(Insert.class); Insert insert = method.getAnnotation(Insert.class);
if (insert != null) { if (insert != null) {
// 查询
String sql = insert.value(); String sql = insert.value();
boolean custom = insert.custom(); boolean custom = insert.custom();
PrepSqlResultImpl handler = sqlHandler.handler(sql, custom, method, args); return invokeDefault(3, sql, custom, rs, method, args);
if (!handler.getSqlStr().trim().toLowerCase().startsWith("insert ")) {
throw new CustomerException("The sql statement does not match, the @Insert annotation can only execute the insert statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info(handler.toString());
Class<?> returnType = method.getReturnType();
boolean b;
if (handler.getArgs().isEmpty()) {
b = rs.executeUpdate(handler.getSqlStr());
} else {
b = rs.executeUpdate(handler.getSqlStr(), handler.getArgs());
}
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
} }
Delete delete = method.getAnnotation(Delete.class); Delete delete = method.getAnnotation(Delete.class);
if (delete != null) { if (delete != null) {
// 查询
String sql = delete.value(); String sql = delete.value();
boolean custom = delete.custom(); boolean custom = delete.custom();
PrepSqlResultImpl handler = sqlHandler.handler(sql, custom, method, args); return invokeDefault(4, sql, custom, rs, method, args);
if (!handler.getSqlStr().trim().toLowerCase().startsWith("delete ")) {
throw new CustomerException("The sql statement does not match, the @Delete annotation can only execute the delete statement, please check whether the sql statement matches!");
}
Util.getLogger(SQL_LOG).info(handler.toString());
Class<?> returnType = method.getReturnType();
boolean b;
if (handler.getArgs().isEmpty()) {
b = rs.executeUpdate(handler.getSqlStr());
} else {
b = rs.executeUpdate(handler.getSqlStr(), handler.getArgs());
}
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
} }
boolean hasBatchInsert = method.isAnnotationPresent(BatchInsert.class); BatchInsert batchInsert = method.getAnnotation(BatchInsert.class);
if (hasBatchInsert) { if (batchInsert != null) {
BatchInsert batchInsert = method.getAnnotation(BatchInsert.class);
String sql = batchInsert.value(); String sql = batchInsert.value();
Class<?> returnType = method.getReturnType();
boolean custom = batchInsert.custom(); boolean custom = batchInsert.custom();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args); return invokeDefault(5, sql, custom, rs, method, args);
Util.getLogger(SQL_LOG).info(batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!");
}
if (!batchSqlResult.getSqlStr().trim().toLowerCase().startsWith("insert ")) {
throw new CustomerException("The sql statement does not match, the @Insert annotation can only execute the insert statement, please check whether the sql statement matches!");
}
boolean b = rs.executeBatchSql(batchSqlResult.getSqlStr(), batchSqlResult.getBatchList());
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
} }
boolean hasBatchUpdate = method.isAnnotationPresent(BatchUpdate.class); BatchUpdate batchUpdate = method.getAnnotation(BatchUpdate.class);
if (hasBatchUpdate) { if (batchUpdate != null) {
BatchUpdate batchUpdate = method.getAnnotation(BatchUpdate.class);
String sql = batchUpdate.value(); String sql = batchUpdate.value();
Class<?> returnType = method.getReturnType();
boolean custom = batchUpdate.custom(); boolean custom = batchUpdate.custom();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args); return invokeDefault(6, sql, custom, rs, method, args);
Util.getLogger(SQL_LOG).info(batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!");
}
if (!batchSqlResult.getSqlStr().trim().toLowerCase().startsWith("update ")) {
throw new CustomerException("The sql statement does not match, the @Update annotation can only execute the update statement, please check whether the sql statement matches!");
}
boolean b = rs.executeBatchSql(batchSqlResult.getSqlStr(), batchSqlResult.getBatchList());
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
} }
boolean hasBatchDelete = method.isAnnotationPresent(BatchDelete.class); BatchDelete batchDelete = method.getAnnotation(BatchDelete.class);
if (hasBatchDelete) { if (batchDelete != null) {
BatchDelete batchDelete = method.getAnnotation(BatchDelete.class);
String sql = batchDelete.value(); String sql = batchDelete.value();
Class<?> returnType = method.getReturnType();
boolean custom = batchDelete.custom(); boolean custom = batchDelete.custom();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args); return invokeDefault(7, sql, custom, rs, method, args);
Util.getLogger(SQL_LOG).info(batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!");
}
if (!batchSqlResult.getSqlStr().trim().toLowerCase().startsWith("delete ")) {
throw new CustomerException("The sql statement does not match, the @Delete annotation can only execute the delete statement, please check whether the sql statement matches!");
}
boolean b = rs.executeBatchSql(batchSqlResult.getSqlStr(), batchSqlResult.getBatchList());
if (returnType.equals(void.class)) {
return null;
}
if (returnType.equals(boolean.class) || returnType.equals(Boolean.class)) {
return b;
}
} }
throw new CustomerException("该方法没有添加注解!请检查是否正确添加注解!@Select、@Update、@Insert、@Delete、@BatchUpdate、@BatchInsert、@BatchDelete"); throw new CustomerException("该方法没有添加注解!请检查是否正确添加注解!@Select、@Update、@Insert、@Delete、@BatchUpdate、@BatchInsert、@BatchDelete");
} }
private Object invokeRsTrans(Object proxy, Method method, Object[] args, String name) { private Object invokeRsTrans(Object proxy, Method method, Object[] args, String name) {
String mapperKey = method.getDeclaringClass().getName(); String mapperKey = method.getDeclaringClass().getName();
String invokeMethod = method.getDeclaringClass().getName() + ":" + method.getName() + " : ";
if (!"".equals(name) && null != name) { if (!"".equals(name) && null != name) {
mapperKey += "." + name; mapperKey += "." + name;
} }
@ -261,7 +325,7 @@ public class RecordsetUtil implements InvocationHandler {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("select ")) { if (!handler.getSqlStr().trim().toLowerCase().startsWith("select ")) {
throw new CustomerException("The sql statement does not match, the @Select annotation can only execute the select statement, please check whether the sql statement matches!"); throw new CustomerException("The sql statement does not match, the @Select annotation can only execute the select statement, please check whether the sql statement matches!");
} }
Util.getLogger(SQL_LOG).info("解析sql===>" + handler); Util.getLogger(SQL_LOG).info(invokeMethod + handler);
try { try {
if (handler.getArgs().isEmpty()) { if (handler.getArgs().isEmpty()) {
rs.executeQuery(handler.getSqlStr()); rs.executeQuery(handler.getSqlStr());
@ -284,7 +348,7 @@ public class RecordsetUtil implements InvocationHandler {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("update ")) { if (!handler.getSqlStr().trim().toLowerCase().startsWith("update ")) {
throw new CustomerException("The sql statement does not match, the @Update annotation can only execute the update statement, please check whether the sql statement matches!"); throw new CustomerException("The sql statement does not match, the @Update annotation can only execute the update statement, please check whether the sql statement matches!");
} }
Util.getLogger(SQL_LOG).info(handler.toString()); Util.getLogger(SQL_LOG).info(invokeMethod + handler);
Class<?> returnType = method.getReturnType(); Class<?> returnType = method.getReturnType();
boolean b; boolean b;
try { try {
@ -320,7 +384,7 @@ public class RecordsetUtil implements InvocationHandler {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("insert ")) { if (!handler.getSqlStr().trim().toLowerCase().startsWith("insert ")) {
throw new CustomerException("The sql statement does not match, the @Insert annotation can only execute the insert statement, please check whether the sql statement matches!"); throw new CustomerException("The sql statement does not match, the @Insert annotation can only execute the insert statement, please check whether the sql statement matches!");
} }
Util.getLogger(SQL_LOG).info(handler.toString()); Util.getLogger(SQL_LOG).info(invokeMethod + handler);
Class<?> returnType = method.getReturnType(); Class<?> returnType = method.getReturnType();
boolean b; boolean b;
try { try {
@ -349,7 +413,7 @@ public class RecordsetUtil implements InvocationHandler {
if (!handler.getSqlStr().trim().toLowerCase().startsWith("delete ")) { if (!handler.getSqlStr().trim().toLowerCase().startsWith("delete ")) {
throw new CustomerException("The sql statement does not match, the @Delete annotation can only execute the delete statement, please check whether the sql statement matches!"); throw new CustomerException("The sql statement does not match, the @Delete annotation can only execute the delete statement, please check whether the sql statement matches!");
} }
Util.getLogger(SQL_LOG).info(handler.toString()); Util.getLogger(SQL_LOG).info(invokeMethod + handler);
Class<?> returnType = method.getReturnType(); Class<?> returnType = method.getReturnType();
boolean b; boolean b;
try { try {
@ -376,7 +440,7 @@ public class RecordsetUtil implements InvocationHandler {
Class<?> returnType = method.getReturnType(); Class<?> returnType = method.getReturnType();
boolean custom = batchInsert.custom(); boolean custom = batchInsert.custom();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args); BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args);
Util.getLogger(SQL_LOG).info(batchSqlResult.toString()); Util.getLogger(SQL_LOG).info(invokeMethod + batchSqlResult.toString());
List<List> batchList = batchSqlResult.getBatchList(); List<List> batchList = batchSqlResult.getBatchList();
if (batchList.isEmpty()) { if (batchList.isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!"); throw new CustomerException("execute batch sql error , batch sql args is empty!");
@ -415,7 +479,7 @@ public class RecordsetUtil implements InvocationHandler {
Class<?> returnType = method.getReturnType(); Class<?> returnType = method.getReturnType();
boolean custom = batchUpdate.custom(); boolean custom = batchUpdate.custom();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args); BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args);
Util.getLogger(SQL_LOG).info(batchSqlResult.toString()); Util.getLogger(SQL_LOG).info(invokeMethod + batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) { if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!"); throw new CustomerException("execute batch sql error , batch sql args is empty!");
} }
@ -456,7 +520,7 @@ public class RecordsetUtil implements InvocationHandler {
Class<?> returnType = method.getReturnType(); Class<?> returnType = method.getReturnType();
boolean custom = batchDelete.custom(); boolean custom = batchDelete.custom();
BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args); BatchSqlResultImpl batchSqlResult = sqlHandler.handlerBatch(sql, custom, method, args);
Util.getLogger(SQL_LOG).info(batchSqlResult.toString()); Util.getLogger(SQL_LOG).info(invokeMethod + batchSqlResult.toString());
if (batchSqlResult.getBatchList().isEmpty()) { if (batchSqlResult.getBatchList().isEmpty()) {
throw new CustomerException("execute batch sql error , batch sql args is empty!"); throw new CustomerException("execute batch sql error , batch sql args is empty!");
} }

View File

@ -41,7 +41,7 @@ public class ResultMapper {
typeHandler.put(Boolean.class, new BooleanTypeHandler()); typeHandler.put(Boolean.class, new BooleanTypeHandler());
typeHandler.put(boolean.class, new BooleanTypeHandler()); typeHandler.put(boolean.class, new BooleanTypeHandler());
typeHandler.put(Date.class, new DataTypeHandler()); typeHandler.put(Date.class, new DataTypeHandler());
typeHandler.put(Float.class, new FloatTypeHandler()); typeHandler.put(float.class, new FloatTypeHandler());
typeHandler.put(Float.class, new FloatTypeHandler()); typeHandler.put(Float.class, new FloatTypeHandler());
typeHandler.put(double.class, new DoubleTypeHandler()); typeHandler.put(double.class, new DoubleTypeHandler());
typeHandler.put(Double.class, new DoubleTypeHandler()); typeHandler.put(Double.class, new DoubleTypeHandler());
@ -319,8 +319,12 @@ public class ResultMapper {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getInt(i + 1)); ((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getInt(i + 1));
continue; continue;
} }
if (DBConstant.DB_TYPE_ORACLE.equals(rs.getDBType())) {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getInt(i + 1));
}
((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getInt(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getInt(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getInt(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getInt(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i], rs.getInt(i + 1));
continue; continue;
} }
if ("FLOAT".equalsIgnoreCase(columnType) || "DOUBLE".equalsIgnoreCase(columnType) || "DECIMAL".equalsIgnoreCase(columnType)) { if ("FLOAT".equalsIgnoreCase(columnType) || "DOUBLE".equalsIgnoreCase(columnType) || "DECIMAL".equalsIgnoreCase(columnType)) {
@ -328,16 +332,24 @@ public class ResultMapper {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getFloat(i + 1)); ((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getFloat(i + 1));
continue; continue;
} }
if (DBConstant.DB_TYPE_ORACLE.equals(rs.getDBType())) {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getFloat(i + 1));
}
((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getFloat(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getFloat(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getFloat(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getFloat(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i], rs.getFloat(i + 1));
continue; continue;
} }
if (enable) { if (enable) {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getString(i + 1)); ((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getString(i + 1));
continue; continue;
} }
if (DBConstant.DB_TYPE_ORACLE.equals(rs.getDBType())) {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getString(i + 1));
}
((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getString(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getString(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getString(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getString(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i], rs.getString(i + 1));
continue; continue;
} }
return o; return o;
@ -386,7 +398,9 @@ public class ResultMapper {
} else { } else {
value = ResultMapper.typeHandler.get(propertyType) == null ? null : ResultMapper.typeHandler.get(propertyType).getValue(rs, fieldName, declaredField); value = ResultMapper.typeHandler.get(propertyType) == null ? null : ResultMapper.typeHandler.get(propertyType).getValue(rs, fieldName, declaredField);
} }
propertyDescriptor.getWriteMethod().invoke(o, value); if (!Objects.isNull(value)) {
propertyDescriptor.getWriteMethod().invoke(o, value);
}
} }
} catch (Exception e) { } catch (Exception e) {
@ -449,8 +463,12 @@ public class ResultMapper {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getInt(i + 1)); ((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getInt(i + 1));
continue; continue;
} }
if (DBConstant.DB_TYPE_ORACLE.equals(rs.getDBType())) {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getInt(i + 1));
}
((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getInt(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getInt(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getInt(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getInt(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i], rs.getInt(i + 1));
continue; continue;
} }
if ("FLOAT".equalsIgnoreCase(columnType) || "DOUBLE".equalsIgnoreCase(columnType) || "DECIMAL".equalsIgnoreCase(columnType)) { if ("FLOAT".equalsIgnoreCase(columnType) || "DOUBLE".equalsIgnoreCase(columnType) || "DECIMAL".equalsIgnoreCase(columnType)) {
@ -458,8 +476,12 @@ public class ResultMapper {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getFloat(i + 1)); ((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getFloat(i + 1));
continue; continue;
} }
if (DBConstant.DB_TYPE_ORACLE.equals(rs.getDBType())) {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getFloat(i + 1));
}
((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getFloat(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getFloat(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getFloat(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getFloat(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i], rs.getFloat(i + 1));
continue; continue;
} }
if (method.isAnnotationPresent(Associations.class)) { if (method.isAnnotationPresent(Associations.class)) {
@ -488,8 +510,12 @@ public class ResultMapper {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getString(i + 1)); ((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getString(i + 1));
continue; continue;
} }
if (DBConstant.DB_TYPE_ORACLE.equals(rs.getDBType())) {
((Map<? super Object, ? super Object>) o).put(Util.toCamelCase(columnName[i]), rs.getString(i + 1));
}
((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getString(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toLowerCase(), rs.getString(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getString(i + 1)); ((Map<? super Object, ? super Object>) o).put(columnName[i].toUpperCase(), rs.getString(i + 1));
((Map<? super Object, ? super Object>) o).put(columnName[i], rs.getString(i + 1));
} }
return o; return o;
} }
@ -528,6 +554,7 @@ public class ResultMapper {
Object value = null; Object value = null;
String fieldName = propertyDescriptor.getName(); String fieldName = propertyDescriptor.getName();
Field declaredField = o.getClass().getDeclaredField(fieldName);
if (Strings.isNullOrEmpty(fieldName)) { if (Strings.isNullOrEmpty(fieldName)) {
fieldName = propertyDescriptor.getDisplayName(); fieldName = propertyDescriptor.getDisplayName();
} }
@ -536,7 +563,20 @@ public class ResultMapper {
if (association != null) { if (association != null) {
if (association.property().equals(fieldName)) { if (association.property().equals(fieldName)) {
Object cassociationValue = association(rs, association, method); Object cassociationValue = association(rs, association, method);
propertyDescriptor.getWriteMethod().invoke(o, cassociationValue); if (cassociationValue == null) {
continue;
}
if (paramType.containsKey(declaredField.getType())) {
cassociationValue = paramType.get(declaredField.getType()).apply(String.valueOf(cassociationValue));
}
try {
propertyDescriptor.getWriteMethod().invoke(o, cassociationValue);
} catch (Exception e) {
Util.getLogger().error("实体数据写入报错:" + fieldName + " => " + value);
if (value != null) {
Util.getLogger().error("查询数据类型: " + value.getClass());
}
}
continue; continue;
} }
} }
@ -546,21 +586,37 @@ public class ResultMapper {
if (collectionMapping != null) { if (collectionMapping != null) {
if (fieldName.equals(collectionMapping.property()) && !"".equals(collectionMapping.property())) { if (fieldName.equals(collectionMapping.property()) && !"".equals(collectionMapping.property())) {
Object collection = collection(rs, collectionMapping, method); Object collection = collection(rs, collectionMapping, method);
propertyDescriptor.getWriteMethod().invoke(o, collection); try {
propertyDescriptor.getWriteMethod().invoke(o, collection);
} catch (Exception e) {
Util.getLogger().error("实体数据写入报错:" + fieldName + " => " + value);
if (value != null) {
Util.getLogger().error("查询数据类型: " + value.getClass());
}
}
continue; continue;
} }
} }
} }
Field declaredField = o.getClass().getDeclaredField(fieldName); TypeHandler typeHandler = ResultMapper.typeHandler.get(propertyType);
if (enable) { if (enable) {
value = ResultMapper.typeHandler.get(propertyType) == null ? null : ResultMapper.typeHandler.get(propertyType).getValue(rs, Util.toUnderlineCase(fieldName), declaredField); value = typeHandler == null ? null : typeHandler.getValue(rs, Util.toUnderlineCase(fieldName), declaredField);
} else { } else {
value = ResultMapper.typeHandler.get(propertyType) == null ? null : ResultMapper.typeHandler.get(propertyType).getValue(rs, fieldName, declaredField); value = typeHandler == null ? null : typeHandler.getValue(rs, fieldName, declaredField);
} }
propertyDescriptor.getWriteMethod().invoke(o, value); try {
if (!Objects.isNull(value)) {
propertyDescriptor.getWriteMethod().invoke(o, value);
}
} catch (Exception e) {
Util.getLogger().error("实体数据写入报错:" + fieldName + " => " + value);
if (value != null) {
Util.getLogger().error("查询数据类型: " + value.getClass());
}
throw e;
}
} }
} catch (Exception e) { } catch (Exception e) {
Util.getLogger().error("报错了,写入数据到实体类报错!\n" + Util.getErrString(e)); Util.getLogger().error("报错了,写入数据到实体类报错!\n" + Util.getErrString(e));
throw new CustomerException(e.getMessage(), e); throw new CustomerException(e.getMessage(), e);
@ -607,6 +663,9 @@ public class ResultMapper {
Id id = annotation.id(); Id id = annotation.id();
String column = annotation.column(); String column = annotation.column();
String columnValue = rs.getString(column); String columnValue = rs.getString(column);
if (Objects.isNull(columnValue) || "".equals(columnValue)) {
columnValue = rs.getString(column.toUpperCase());
}
if (Objects.isNull(columnValue) || "".equals(columnValue)) { if (Objects.isNull(columnValue) || "".equals(columnValue)) {
return null; return null;
} }
@ -665,6 +724,9 @@ public class ResultMapper {
Id id = annotation.id(); Id id = annotation.id();
String column = annotation.column(); String column = annotation.column();
String columnValue = rs.getString(column); String columnValue = rs.getString(column);
if (Objects.isNull(columnValue) || "".equals(columnValue)) {
columnValue = rs.getString(column.toUpperCase());
}
if (Objects.isNull(columnValue) || "".equals(columnValue)) { if (Objects.isNull(columnValue) || "".equals(columnValue)) {
return null; return null;
} }

View File

@ -1,5 +1,7 @@
package aiyh.utils.sqlUtil.sqlResult.impl; package aiyh.utils.sqlUtil.sqlResult.impl;
import aiyh.utils.recordset.FormatSqlUtil;
import java.util.List; import java.util.List;
/** /**
@ -10,27 +12,27 @@ import java.util.List;
public class BatchSqlResultImpl implements aiyh.utils.sqlUtil.sqlResult.SqlResult { public class BatchSqlResultImpl implements aiyh.utils.sqlUtil.sqlResult.SqlResult {
private final String sqlStr; private final String sqlStr;
private final List<List> batchList; private final List<List> batchList;
public BatchSqlResultImpl(String sqlStr, List<List> batchList) { public BatchSqlResultImpl(String sqlStr, List<List> batchList) {
this.sqlStr = sqlStr; this.sqlStr = sqlStr;
this.batchList = batchList; this.batchList = batchList;
} }
public String getSqlStr() { public String getSqlStr() {
return sqlStr; return sqlStr;
} }
public List<List> getBatchList() { public List<List> getBatchList() {
return batchList; return batchList;
} }
@Override @Override
public String toString() { public String toString() {
return "BatchSqlResultImpl{" + return "BatchSqlResultImpl{" +
"sqlStr='" + sqlStr + '\'' + "sqlStr='\n" + FormatSqlUtil.formatSql(sqlStr) + "\n'" +
", batchList=" + batchList + ", batchList=" + batchList +
'}'; '}';
} }
} }

View File

@ -1,5 +1,6 @@
package aiyh.utils.sqlUtil.sqlResult.impl; package aiyh.utils.sqlUtil.sqlResult.impl;
import aiyh.utils.recordset.FormatSqlUtil;
import aiyh.utils.sqlUtil.sqlResult.SqlResult; import aiyh.utils.sqlUtil.sqlResult.SqlResult;
import java.util.List; import java.util.List;
@ -28,11 +29,11 @@ public class PrepSqlResultImpl implements SqlResult {
return args; return args;
} }
@Override @Override
public String toString() { public String toString() {
return "PrepSqlResultImpl{" + return "PrepSqlResultImpl{" +
"sqlStr='" + sqlStr + '\'' + "sqlStr='\n" + FormatSqlUtil.formatSql(sqlStr) + "\n'" +
", args=" + args + ", args=" + args +
'}'; '}';
} }
} }

View File

@ -0,0 +1,168 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.annotation.scanner.AnnotationScanner;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* {@link AnnotationSynthesizer}
*
* @author huangchengxing
*/
public abstract class AbstractAnnotationSynthesizer<T> implements AnnotationSynthesizer {
/**
*
*/
protected final T source;
/**
*
*/
protected final Map<Class<? extends Annotation>, SynthesizedAnnotation> synthesizedAnnotationMap;
/**
*
*/
private final Map<Class<? extends Annotation>, Annotation> synthesizedProxyAnnotations;
/**
*
*/
protected final SynthesizedAnnotationSelector annotationSelector;
/**
*
*/
protected final Collection<SynthesizedAnnotationPostProcessor> postProcessors;
/**
*
*/
protected final AnnotationScanner annotationScanner;
/**
*
*
* @param source
* @param annotationSelector
* @param annotationPostProcessors
* @param annotationScanner
*/
protected AbstractAnnotationSynthesizer(
T source,
SynthesizedAnnotationSelector annotationSelector,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
Assert.notNull(source, "source must not null");
Assert.notNull(annotationSelector, "annotationSelector must not null");
Assert.notNull(annotationPostProcessors, "annotationPostProcessors must not null");
Assert.notNull(annotationPostProcessors, "annotationScanner must not null");
this.source = source;
this.annotationSelector = annotationSelector;
this.annotationScanner = annotationScanner;
this.postProcessors = CollUtil.unmodifiable(
CollUtil.sort(annotationPostProcessors, Comparator.comparing(SynthesizedAnnotationPostProcessor::order))
);
this.synthesizedProxyAnnotations = new LinkedHashMap<>();
this.synthesizedAnnotationMap = MapUtil.unmodifiable(loadAnnotations());
annotationPostProcessors.forEach(processor ->
synthesizedAnnotationMap.values().forEach(synthesized -> processor.process(synthesized, this))
);
}
/**
*
*
* @return
*/
protected abstract Map<Class<? extends Annotation>, SynthesizedAnnotation> loadAnnotations();
/**
*
*
* @param annotationType
* @param annotation
* @param <A>
* @return
*/
protected abstract <A extends Annotation> A synthesize(Class<A> annotationType, SynthesizedAnnotation annotation);
/**
*
*
* @return
*/
@Override
public T getSource() {
return source;
}
/**
*
*
* @return
*/
@Override
public SynthesizedAnnotationSelector getAnnotationSelector() {
return annotationSelector;
}
/**
*
*
* @return
*/
@Override
public Collection<SynthesizedAnnotationPostProcessor> getAnnotationPostProcessors() {
return postProcessors;
}
/**
*
*
* @param annotationType
* @return
*/
@Override
public SynthesizedAnnotation getSynthesizedAnnotation(Class<?> annotationType) {
return synthesizedAnnotationMap.get(annotationType);
}
/**
*
*
* @return
*/
@Override
public Map<Class<? extends Annotation>, SynthesizedAnnotation> getAllSynthesizedAnnotation() {
return synthesizedAnnotationMap;
}
/**
*
*
* @param annotationType
* @param <A>
* @return
*/
@SuppressWarnings("unchecked")
@Override
public <A extends Annotation> A synthesize(Class<A> annotationType) {
return (A)synthesizedProxyAnnotations.computeIfAbsent(annotationType, type -> {
final SynthesizedAnnotation synthesizedAnnotation = synthesizedAnnotationMap.get(annotationType);
return ObjectUtil.isNull(synthesizedAnnotation) ?
null : synthesize(annotationType, synthesizedAnnotation);
});
}
}

View File

@ -0,0 +1,163 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.lang.Opt;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
/**
* {@link SynthesizedAnnotationPostProcessor}
* {@link Link}
*
* @author huangchengxing
* @see MirrorLinkAnnotationPostProcessor
* @see AliasLinkAnnotationPostProcessor
*/
public abstract class AbstractLinkAnnotationPostProcessor implements SynthesizedAnnotationPostProcessor {
/**
* {@link Link}{@link Link#type()}{@link #processTypes()}
* {@link Link}{@link SynthesizedAggregateAnnotation}
*
* {@link #processLinkedAttribute}
*
* @param synthesizedAnnotation
* @param synthesizer
*/
@Override
public void process(SynthesizedAnnotation synthesizedAnnotation, AnnotationSynthesizer synthesizer) {
final Map<String, AnnotationAttribute> attributeMap = new HashMap<>(synthesizedAnnotation.getAttributes());
attributeMap.forEach((originalAttributeName, originalAttribute) -> {
// 获取注解
final Link link = getLinkAnnotation(originalAttribute, processTypes());
if (ObjectUtil.isNull(link)) {
return;
}
// 获取注解属性
final SynthesizedAnnotation linkedAnnotation = getLinkedAnnotation(link, synthesizer, synthesizedAnnotation.annotationType());
if (ObjectUtil.isNull(linkedAnnotation)) {
return;
}
final AnnotationAttribute linkedAttribute = linkedAnnotation.getAttributes().get(link.attribute());
// 处理
processLinkedAttribute(
synthesizer, link,
synthesizedAnnotation, synthesizedAnnotation.getAttributes().get(originalAttributeName),
linkedAnnotation, linkedAttribute
);
});
}
// =========================== 抽象方法 ===========================
/**
* {@link Link}{@link Link#type()}
*
* @return {@link RelationType}
*/
protected abstract RelationType[] processTypes();
/**
*
*
* @param synthesizer
* @param annotation {@code originalAttribute}{@link Link}
* @param originalAnnotation {@link SynthesizedAnnotation}
* @param originalAttribute {@code originalAnnotation}
* @param linkedAnnotation {@link Link}
* @param linkedAttribute {@link Link}{@code originalAnnotation}
*/
protected abstract void processLinkedAttribute(
AnnotationSynthesizer synthesizer, Link annotation,
SynthesizedAnnotation originalAnnotation, AnnotationAttribute originalAttribute,
SynthesizedAnnotation linkedAnnotation, AnnotationAttribute linkedAttribute
);
// =========================== @Link注解的处理 ===========================
/**
* {@link Link}
*
* @param attribute
* @param relationTypes
* @return
*/
protected Link getLinkAnnotation(AnnotationAttribute attribute, RelationType... relationTypes) {
return Opt.ofNullable(attribute)
.map(t -> AnnotationUtil.getSynthesizedAnnotation(attribute.getAttribute(), Link.class))
.filter(a -> ArrayUtil.contains(relationTypes, a.type()))
.get();
}
/**
* {@link Link#type()}
*
* @param annotation {@link Link}
* @param synthesizer
* @param defaultType
* @return {@link SynthesizedAnnotation}
*/
protected SynthesizedAnnotation getLinkedAnnotation(Link annotation, AnnotationSynthesizer synthesizer, Class<? extends Annotation> defaultType) {
final Class<?> targetAnnotationType = getLinkedAnnotationType(annotation, defaultType);
return synthesizer.getSynthesizedAnnotation(targetAnnotationType);
}
/**
* {@link Link#annotation()}{@code Annotation#getClass()}{@code defaultType}
* {@link Link#annotation()}
*
* @param annotation {@link Link}
* @param defaultType
* @return
*/
protected Class<?> getLinkedAnnotationType(Link annotation, Class<?> defaultType) {
return ObjectUtil.equals(annotation.annotation(), Annotation.class) ?
defaultType : annotation.annotation();
}
// =========================== 注解属性的校验 ===========================
/**
*
*
* @param original
* @param alias
*/
protected void checkAttributeType(AnnotationAttribute original, AnnotationAttribute alias) {
Assert.equals(
original.getAttributeType(), alias.getAttributeType(),
"return type of the linked attribute [{}] is inconsistent with the original [{}]",
original.getAttribute(), alias.getAttribute()
);
}
/**
* {@link Link}
*
* @param original {@link Link}
* @param linked {@link Link}
*/
protected void checkLinkedSelf(AnnotationAttribute original, AnnotationAttribute linked) {
boolean linkSelf = (original == linked) || ObjectUtil.equals(original.getAttribute(), linked.getAttribute());
Assert.isFalse(linkSelf, "cannot link self [{}]", original.getAttribute());
}
/**
* {@link Link}
*
* @param original {@link Link}
* @param linkedAttribute {@link Link}
* @param annotation {@link Link}
*/
protected void checkLinkedAttributeNotNull(AnnotationAttribute original, AnnotationAttribute linkedAttribute, Link annotation) {
Assert.notNull(linkedAttribute, "cannot find linked attribute [{}] of original [{}] in [{}]",
original.getAttribute(), annotation.attribute(),
getLinkedAnnotationType(annotation, original.getAnnotationType())
);
}
}

View File

@ -0,0 +1,71 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* {@link WrappedAnnotationAttribute}
*
* @author huangchengxing
* @see ForceAliasedAnnotationAttribute
* @see AliasedAnnotationAttribute
* @see MirroredAnnotationAttribute
*/
public abstract class AbstractWrappedAnnotationAttribute implements WrappedAnnotationAttribute {
protected final AnnotationAttribute original;
protected final AnnotationAttribute linked;
protected AbstractWrappedAnnotationAttribute(AnnotationAttribute original, AnnotationAttribute linked) {
Assert.notNull(original, "target must not null");
Assert.notNull(linked, "linked must not null");
this.original = original;
this.linked = linked;
}
@Override
public AnnotationAttribute getOriginal() {
return original;
}
@Override
public AnnotationAttribute getLinked() {
return linked;
}
@Override
public AnnotationAttribute getNonWrappedOriginal() {
AnnotationAttribute curr = null;
AnnotationAttribute next = original;
while (next != null) {
curr = next;
next = next.isWrapped() ? ((WrappedAnnotationAttribute)curr).getOriginal() : null;
}
return curr;
}
@Override
public Collection<AnnotationAttribute> getAllLinkedNonWrappedAttributes() {
List<AnnotationAttribute> leafAttributes = new ArrayList<>();
collectLeafAttribute(this, leafAttributes);
return leafAttributes;
}
private void collectLeafAttribute(AnnotationAttribute curr, List<AnnotationAttribute> leafAttributes) {
if (ObjectUtil.isNull(curr)) {
return;
}
if (!curr.isWrapped()) {
leafAttributes.add(curr);
return;
}
WrappedAnnotationAttribute wrappedAttribute = (WrappedAnnotationAttribute)curr;
collectLeafAttribute(wrappedAttribute.getOriginal(), leafAttributes);
collectLeafAttribute(wrappedAttribute.getLinked(), leafAttributes);
}
}

View File

@ -0,0 +1,27 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
/**
*
*
* @author huangchengxing
*/
public interface AggregateAnnotation extends Annotation {
/**
*
*
* @param annotationType
* @return
*/
boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
/**
*
*
* @return
*/
Annotation[] getAnnotations();
}

View File

@ -0,0 +1,26 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 使BeanBeanMap
*
* @author Looly
* @since 5.1.1
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface Alias {
/**
* 使
*
* @return
*/
String value();
}

View File

@ -0,0 +1,66 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.lang.Opt;
import aiyh.utils.tool.cn.hutool.core.map.ForestMap;
import aiyh.utils.tool.cn.hutool.core.map.LinkedForestMap;
import aiyh.utils.tool.cn.hutool.core.map.TreeEntry;
import aiyh.utils.tool.cn.hutool.core.util.ClassUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.util.Map;
/**
* <p>{@link Alias}<br>
* {@link Alias}
* {@link ForceAliasedAnnotationAttribute}
*
* @author huangchengxing
* @see Alias
* @see ForceAliasedAnnotationAttribute
*/
public class AliasAnnotationPostProcessor implements SynthesizedAnnotationPostProcessor {
@Override
public int order() {
return Integer.MIN_VALUE;
}
@Override
public void process(SynthesizedAnnotation synthesizedAnnotation, AnnotationSynthesizer synthesizer) {
final Map<String, AnnotationAttribute> attributeMap = synthesizedAnnotation.getAttributes();
// 记录别名与属性的关系
final ForestMap<String, AnnotationAttribute> attributeAliasMappings = new LinkedForestMap<>(false);
attributeMap.forEach((attributeName, attribute) -> {
final String alias = Opt.ofNullable(attribute.getAnnotation(Alias.class))
.map(Alias::value)
.orElse(null);
if (ObjectUtil.isNull(alias)) {
return;
}
final AnnotationAttribute aliasAttribute = attributeMap.get(alias);
Assert.notNull(aliasAttribute, "no method for alias: [{}]", alias);
attributeAliasMappings.putLinkedNodes(alias, aliasAttribute, attributeName, attribute);
});
// 处理别名
attributeMap.forEach((attributeName, attribute) -> {
final AnnotationAttribute resolvedAttribute = Opt.ofNullable(attributeName)
.map(attributeAliasMappings::getRootNode)
.map(TreeEntry::getValue)
.orElse(attribute);
Assert.isTrue(
ObjectUtil.isNull(resolvedAttribute)
|| ClassUtil.isAssignable(attribute.getAttributeType(), resolvedAttribute.getAttributeType()),
"return type of the root alias method [{}] is inconsistent with the original [{}]",
resolvedAttribute.getClass(), attribute.getAttributeType()
);
if (attribute != resolvedAttribute) {
attributeMap.put(attributeName, new ForceAliasedAnnotationAttribute(attribute, resolvedAttribute));
}
});
synthesizedAnnotation.setAttributes(attributeMap);
}
}

View File

@ -0,0 +1,39 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>{@link Link}
* <ul>
* <li></li>
* <li></li>
* </ul>
* <b>{@link Link}{@link ForceAliasFor}{@link MirrorFor}使</b>
*
* @author huangchengxing
* @see Link
* @see RelationType#ALIAS_FOR
*/
@Link(type = RelationType.ALIAS_FOR)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface AliasFor {
/**
*
*
* @return
*/
@Link(annotation = Link.class, attribute = "annotation", type = RelationType.FORCE_ALIAS_FOR)
Class<? extends Annotation> annotation() default Annotation.class;
/**
* {@link #annotation()}
*
* @return
*/
@Link(annotation = Link.class, attribute = "attribute", type = RelationType.FORCE_ALIAS_FOR)
String attribute() default "";
}

View File

@ -0,0 +1,126 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.lang.Opt;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.util.function.BinaryOperator;
/**
* <p>{@link Link}{@link Link#type()}
* {@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}<br>
* {@link Link}
* {@link AliasedAnnotationAttribute}{@link ForceAliasedAnnotationAttribute}
*
* @author huangchengxing
* @see RelationType#ALIAS_FOR
* @see AliasedAnnotationAttribute
* @see RelationType#FORCE_ALIAS_FOR
* @see ForceAliasedAnnotationAttribute
*/
public class AliasLinkAnnotationPostProcessor extends AbstractLinkAnnotationPostProcessor {
private static final RelationType[] PROCESSED_RELATION_TYPES = new RelationType[]{ RelationType.ALIAS_FOR, RelationType.FORCE_ALIAS_FOR };
@Override
public int order() {
return Integer.MIN_VALUE + 2;
}
/**
* {@link Link#type()}{@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}
*
* @return {@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}
*/
@Override
protected RelationType[] processTypes() {
return PROCESSED_RELATION_TYPES;
}
/**
* {@link Link}{@link Link#type()}
* {@link RelationType#ALIAS_FOR}{@link RelationType#FORCE_ALIAS_FOR}
* {@link AliasedAnnotationAttribute}{@link ForceAliasedAnnotationAttribute}
*
*
* @param synthesizer
* @param annotation {@code originalAttribute}{@link Link}
* @param originalAnnotation {@link SynthesizedAnnotation}
* @param originalAttribute {@code originalAnnotation}
* @param linkedAnnotation {@link Link}
* @param linkedAttribute {@link Link}{@code originalAnnotation}
*/
@Override
protected void processLinkedAttribute(
AnnotationSynthesizer synthesizer, Link annotation,
SynthesizedAnnotation originalAnnotation, AnnotationAttribute originalAttribute,
SynthesizedAnnotation linkedAnnotation, AnnotationAttribute linkedAttribute) {
// 校验别名关系
checkAliasRelation(annotation, originalAttribute, linkedAttribute);
// 处理aliasFor类型的关系
if (RelationType.ALIAS_FOR.equals(annotation.type())) {
wrappingLinkedAttribute(synthesizer, originalAttribute, linkedAttribute, AliasedAnnotationAttribute::new);
return;
}
// 处理forceAliasFor类型的关系
wrappingLinkedAttribute(synthesizer, originalAttribute, linkedAttribute, ForceAliasedAnnotationAttribute::new);
}
/**
*
*/
private void wrappingLinkedAttribute(
AnnotationSynthesizer synthesizer, AnnotationAttribute originalAttribute, AnnotationAttribute aliasAttribute, BinaryOperator<AnnotationAttribute> wrapping) {
// 不是包装属性
if (!aliasAttribute.isWrapped()) {
processAttribute(synthesizer, originalAttribute, aliasAttribute, wrapping);
return;
}
// 是包装属性
final AbstractWrappedAnnotationAttribute wrapper = (AbstractWrappedAnnotationAttribute)aliasAttribute;
wrapper.getAllLinkedNonWrappedAttributes().forEach(
t -> processAttribute(synthesizer, originalAttribute, t, wrapping)
);
}
/**
*
*/
private void processAttribute(
AnnotationSynthesizer synthesizer, AnnotationAttribute originalAttribute,
AnnotationAttribute target, BinaryOperator<AnnotationAttribute> wrapping) {
Opt.ofNullable(target.getAnnotationType())
.map(synthesizer::getSynthesizedAnnotation)
.ifPresent(t -> t.replaceAttribute(target.getAttributeName(), old -> wrapping.apply(old, originalAttribute)));
}
/**
*
*/
private void checkAliasRelation(Link annotation, AnnotationAttribute originalAttribute, AnnotationAttribute linkedAttribute) {
checkLinkedAttributeNotNull(originalAttribute, linkedAttribute, annotation);
checkAttributeType(originalAttribute, linkedAttribute);
checkCircularDependency(originalAttribute, linkedAttribute);
}
/**
*
*/
private void checkCircularDependency(AnnotationAttribute original, AnnotationAttribute alias) {
checkLinkedSelf(original, alias);
Link annotation = getLinkAnnotation(alias, RelationType.ALIAS_FOR, RelationType.FORCE_ALIAS_FOR);
if (ObjectUtil.isNull(annotation)) {
return;
}
final Class<?> aliasAnnotationType = getLinkedAnnotationType(annotation, alias.getAnnotationType());
if (ObjectUtil.notEqual(aliasAnnotationType, original.getAnnotationType())) {
return;
}
Assert.notEquals(
annotation.attribute(), original.getAttributeName(),
"circular reference between the alias attribute [{}] and the original attribute [{}]",
alias.getAttribute(), original.getAttribute()
);
}
}

View File

@ -0,0 +1,36 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
/**
* <p>
*
*
* @author huangchengxing
* @see AliasLinkAnnotationPostProcessor
* @see RelationType#ALIAS_FOR
*/
public class AliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute {
protected AliasedAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) {
super(origin, linked);
}
/**
* {@link #linked}{@link #original}{@link #linked}
*
* @return
*/
@Override
public Object getValue() {
return linked.isValueEquivalentToDefaultValue() ? super.getValue() : linked.getValue();
}
/**
* {@link #original}{@link #linked}{@code true}
*
* @return
*/
@Override
public boolean isValueEquivalentToDefaultValue() {
return linked.isValueEquivalentToDefaultValue() && original.isValueEquivalentToDefaultValue();
}
}

View File

@ -0,0 +1,104 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* <p>{@link Method}<br>
* {@link SynthesizedAggregateAnnotation}
* {@link SynthesizedAnnotation}
* 使
*
* <p>{@link SynthesizedAnnotationPostProcessor}
*
* @author huangchengxing
* @see SynthesizedAnnotationPostProcessor
* @see WrappedAnnotationAttribute
* @see CacheableAnnotationAttribute
* @see AbstractWrappedAnnotationAttribute
* @see ForceAliasedAnnotationAttribute
* @see AliasedAnnotationAttribute
* @see MirroredAnnotationAttribute
*/
public interface AnnotationAttribute {
/**
*
*
* @return
*/
Annotation getAnnotation();
/**
*
*
* @return
*/
Method getAttribute();
/**
*
*
* @return
*/
default Class<?> getAnnotationType() {
return getAttribute().getDeclaringClass();
}
/**
*
*
* @return
*/
default String getAttributeName() {
return getAttribute().getName();
}
/**
*
*
* @return
*/
default Object getValue() {
return ReflectUtil.invoke(getAnnotation(), getAttribute());
}
/**
*
*
* @return
*/
boolean isValueEquivalentToDefaultValue();
/**
*
*
* @return
*/
default Class<?> getAttributeType() {
return getAttribute().getReturnType();
}
/**
*
*
* @param <T>
* @param annotationType
* @return
*/
default <T extends Annotation> T getAnnotation(Class<T> annotationType) {
return getAttribute().getAnnotation(annotationType);
}
/**
* {@link WrappedAnnotationAttribute}
*
* @return boolean
*/
default boolean isWrapped() {
return false;
}
}

View File

@ -0,0 +1,18 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
/**
*
*/
@FunctionalInterface
public interface AnnotationAttributeValueProvider {
/**
*
*
* @param attributeName
* @param attributeType
* @return
*/
Object getAttributeValue(String attributeName, Class<?> attributeType);
}

View File

@ -0,0 +1,88 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* <br>
* {@link Alias}
*
* @param <T>
* @since 5.7.23
*/
public class AnnotationProxy<T extends Annotation> implements Annotation, InvocationHandler, Serializable {
private static final long serialVersionUID = 1L;
private final T annotation;
private final Class<T> type;
private final Map<String, Object> attributes;
/**
*
*
* @param annotation
*/
public AnnotationProxy(T annotation) {
this.annotation = annotation;
//noinspection unchecked
this.type = (Class<T>) annotation.annotationType();
this.attributes = initAttributes();
}
@Override
public Class<? extends Annotation> annotationType() {
return type;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 注解别名
Alias alias = method.getAnnotation(Alias.class);
if(null != alias){
final String name = alias.value();
if(StrUtil.isNotBlank(name)){
if(false == attributes.containsKey(name)){
throw new IllegalArgumentException(StrUtil.format("No method for alias: [{}]", name));
}
return attributes.get(name);
}
}
final Object value = attributes.get(method.getName());
if (value != null) {
return value;
}
return method.invoke(this, args);
}
/**
* <br>
* attributes
*
* @return
*/
private Map<String, Object> initAttributes() {
final Method[] methods = ReflectUtil.getMethods(this.type);
final Map<String, Object> attributes = new HashMap<>(methods.length, 1);
for (Method method : methods) {
// 跳过匿名内部类自动生成的方法
if (method.isSynthetic()) {
continue;
}
attributes.put(method.getName(), ReflectUtil.invoke(this.annotation, method));
}
return attributes;
}
}

View File

@ -0,0 +1,77 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Map;
/**
* <p>{@link #getSource()}
*
*
* <p>
* 使{@link SynthesizedAnnotationSelector}
* {@link SynthesizedAnnotation}
* {@link SynthesizedAggregateAnnotation}<br>
* {@link SynthesizedAnnotationSelector}
*
*
* <p>
* {@link SynthesizedAnnotationPostProcessor}
*
* {@link Link}<br>
* {@link SynthesizedAnnotationPostProcessor}
*
*
* <p>使{@link #synthesize(Class)}
*
*
* @author huangchengxing
*/
public interface AnnotationSynthesizer {
/**
*
*
* @return
*/
Object getSource();
/**
*
*
* @return
*/
SynthesizedAnnotationSelector getAnnotationSelector();
/**
*
*
* @return
*/
Collection<SynthesizedAnnotationPostProcessor> getAnnotationPostProcessors();
/**
*
*
* @param annotationType
* @return
*/
SynthesizedAnnotation getSynthesizedAnnotation(Class<?> annotationType);
/**
*
*
* @return
*/
Map<Class<? extends Annotation>, SynthesizedAnnotation> getAllSynthesizedAnnotation();
/**
*
*
* @param annotationType
* @param <T>
* @return
*/
<T extends Annotation> T synthesize(Class<T> annotationType);
}

View File

@ -0,0 +1,576 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.annotation.scanner.AnnotationScanner;
import aiyh.utils.tool.cn.hutool.core.annotation.scanner.MetaAnnotationScanner;
import aiyh.utils.tool.cn.hutool.core.annotation.scanner.MethodAnnotationScanner;
import aiyh.utils.tool.cn.hutool.core.annotation.scanner.TypeAnnotationScanner;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.exceptions.UtilException;
import aiyh.utils.tool.cn.hutool.core.lang.Opt;
import aiyh.utils.tool.cn.hutool.core.lang.func.Func1;
import aiyh.utils.tool.cn.hutool.core.lang.func.LambdaUtil;
import aiyh.utils.tool.cn.hutool.core.util.*;
import java.lang.annotation.*;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* <br>
*
*
* @author looly
* @since 4.0.9
*/
public class AnnotationUtil {
/**
*
*/
static final Set<Class<? extends Annotation>> META_ANNOTATIONS = CollUtil.newHashSet(Target.class, //
Retention.class, //
Inherited.class, //
Documented.class, //
SuppressWarnings.class, //
Override.class, //
Deprecated.class//
);
/**
* Jdk<br>
*
* <ul>
* <li>{@link Target}</li>
* <li>{@link Retention}</li>
* <li>{@link Inherited}</li>
* <li>{@link Documented}</li>
* <li>{@link SuppressWarnings}</li>
* <li>{@link Override}</li>
* <li>{@link Deprecated}</li>
* </ul>
*
* @param annotationType
* @return Jdk
*/
public static boolean isJdkMetaAnnotation(Class<? extends Annotation> annotationType) {
return META_ANNOTATIONS.contains(annotationType);
}
/**
* Jdk<br>
*
* <ul>
* <li>{@link Target}</li>
* <li>{@link Retention}</li>
* <li>{@link Inherited}</li>
* <li>{@link Documented}</li>
* <li>{@link SuppressWarnings}</li>
* <li>{@link Override}</li>
* <li>{@link Deprecated}</li>
* </ul>
*
* @param annotationType
* @return Jdk
*/
public static boolean isNotJdkMateAnnotation(Class<? extends Annotation> annotationType) {
return false == isJdkMetaAnnotation(annotationType);
}
/**
*
*
* @param annotationEle
* @return
*/
public static CombinationAnnotationElement toCombination(AnnotatedElement annotationEle) {
if (annotationEle instanceof CombinationAnnotationElement) {
return (CombinationAnnotationElement) annotationEle;
}
return new CombinationAnnotationElement(annotationEle);
}
/**
*
*
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param isToCombination
* @return
*/
public static Annotation[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination) {
return getAnnotations(annotationEle, isToCombination, (Predicate<Annotation>) null);
}
/**
*
*
* @param <T>
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @return
* @since 5.8.0
*/
public static <T> T[] getCombinationAnnotations(AnnotatedElement annotationEle, Class<T> annotationType) {
return getAnnotations(annotationEle, true, annotationType);
}
/**
*
*
* @param <T>
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param isToCombination
* @param annotationType
* @return
* @since 5.8.0
*/
public static <T> T[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination, Class<T> annotationType) {
final Annotation[] annotations = getAnnotations(annotationEle, isToCombination,
(annotation -> null == annotationType || annotationType.isAssignableFrom(annotation.getClass())));
final T[] result = ArrayUtil.newArray(annotationType, annotations.length);
for (int i = 0; i < annotations.length; i++) {
//noinspection unchecked
result[i] = (T) annotations[i];
}
return result;
}
/**
*
*
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param isToCombination
* @param predicate {@link Predicate#test(Object)}{@code true}
* @return {@link AnnotatedElement}{@code null}{@code null}
* @since 5.8.0
*/
public static Annotation[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination, Predicate<Annotation> predicate) {
if (null == annotationEle) {
return null;
}
if (isToCombination) {
if (null == predicate) {
return toCombination(annotationEle).getAnnotations();
}
return CombinationAnnotationElement.of(annotationEle, predicate).getAnnotations();
}
final Annotation[] result = annotationEle.getAnnotations();
if (null == predicate) {
return result;
}
return ArrayUtil.filter(result, predicate::test);
}
/**
*
*
* @param <A>
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @return
*/
public static <A extends Annotation> A getAnnotation(AnnotatedElement annotationEle, Class<A> annotationType) {
return (null == annotationEle) ? null : toCombination(annotationEle).getAnnotation(annotationType);
}
/**
*
*
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @return
* @since 5.4.2
*/
public static boolean hasAnnotation(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) {
return null != getAnnotation(annotationEle, annotationType);
}
/**
* <br>
* null
*
* @param <T>
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @return
* @throws UtilException
*/
public static <T> T getAnnotationValue(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) throws UtilException {
return getAnnotationValue(annotationEle, annotationType, "value");
}
/**
* <br>
* null
*
* @param <T>
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @param propertyName name() name
* @return
* @throws UtilException
*/
public static <T> T getAnnotationValue(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType, String propertyName) throws UtilException {
final Annotation annotation = getAnnotation(annotationEle, annotationType);
if (null == annotation) {
return null;
}
final Method method = ReflectUtil.getMethodOfObj(annotation, propertyName);
if (null == method) {
return null;
}
return ReflectUtil.invoke(annotation, method);
}
/**
* <br>
* null
*
* @param <A>
* @param <R>
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param propertyName name() name
* @return
* @throws UtilException
* @since 5.8.9
*/
public static <A extends Annotation, R> R getAnnotationValue(AnnotatedElement annotationEle, Func1<A, R> propertyName) {
if (propertyName == null) {
return null;
} else {
final SerializedLambda lambda = LambdaUtil.resolve(propertyName);
final String instantiatedMethodType = lambda.getInstantiatedMethodType();
final Class<A> annotationClass = ClassUtil.loadClass(StrUtil.sub(instantiatedMethodType, 2, StrUtil.indexOf(instantiatedMethodType, ';')));
return getAnnotationValue(annotationEle, annotationClass, lambda.getImplMethodName());
}
}
/**
* <br>
* null
*
* @param annotationEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @return
* @throws UtilException
*/
public static Map<String, Object> getAnnotationValueMap(AnnotatedElement annotationEle, Class<? extends Annotation> annotationType) throws UtilException {
final Annotation annotation = getAnnotation(annotationEle, annotationType);
if (null == annotation) {
return null;
}
final Method[] methods = ReflectUtil.getMethods(annotationType, t -> {
if (ArrayUtil.isEmpty(t.getParameterTypes())) {
// 只读取无参方法
final String name = t.getName();
// 跳过自有的几个方法
return (false == "hashCode".equals(name)) //
&& (false == "toString".equals(name)) //
&& (false == "annotationType".equals(name));
}
return false;
});
final HashMap<String, Object> result = new HashMap<>(methods.length, 1);
for (Method method : methods) {
result.put(method.getName(), ReflectUtil.invoke(annotation, method));
}
return result;
}
/**
* SOURCECLASSRUNTIME CLASS
*
* @param annotationType
* @return
*/
public static RetentionPolicy getRetentionPolicy(Class<? extends Annotation> annotationType) {
final Retention retention = annotationType.getAnnotation(Retention.class);
if (null == retention) {
return RetentionPolicy.CLASS;
}
return retention.value();
}
/**
* TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER
*
* @param annotationType
* @return
*/
public static ElementType[] getTargetType(Class<? extends Annotation> annotationType) {
final Target target = annotationType.getAnnotation(Target.class);
if (null == target) {
return new ElementType[]{ElementType.TYPE, //
ElementType.FIELD, //
ElementType.METHOD, //
ElementType.PARAMETER, //
ElementType.CONSTRUCTOR, //
ElementType.LOCAL_VARIABLE, //
ElementType.ANNOTATION_TYPE, //
ElementType.PACKAGE//
};
}
return target.value();
}
/**
* Javadoc
*
* @param annotationType
* @return Javadoc
*/
public static boolean isDocumented(Class<? extends Annotation> annotationType) {
return annotationType.isAnnotationPresent(Documented.class);
}
/**
* false
*
* @param annotationType
* @return Javadoc
*/
public static boolean isInherited(Class<? extends Annotation> annotationType) {
return annotationType.isAnnotationPresent(Inherited.class);
}
/**
* {@link Class}{@link #META_ANNOTATIONS}JDK
* {@code annotationType}{@link Class#getAnnotations()}
*
* <p><br>
* {@code annotationType} AABBCD
* <pre>
* |-&gt; C.class [@a, @b]
* A.class -&gt; B.class [@a] -|
* |-&gt; D.class [@a, @c]
* </pre>
* A {@code [@a, @a, @b, @a, @c]}
*
* @param annotationType
* @return
* @see MetaAnnotationScanner
*/
public static List<Annotation> scanMetaAnnotation(Class<? extends Annotation> annotationType) {
return AnnotationScanner.DIRECTLY_AND_META_ANNOTATION.getAnnotationsIfSupport(annotationType);
}
/**
* <p>{@link Class}{@link #META_ANNOTATIONS}JDK,
* /{@link Class#getAnnotations()}<br>
* 广
* <ul>
* <li></li>
* <li>{@code targetClass}</li>
* <li>/</li>
* </ul>
* /{@link Class}{@link Class#getAnnotations()}
*
* <p><br>
* {@code targetClass}{@code A.class}{@code A.class}{@code B.class}{@code C.class}
*
* <pre>
* |-&gt; B.class [@a, @b]
* A.class [@a] -|
* |-&gt; C.class [@a, @c]
* </pre>
* {@code [@a, @a, @b, @a, @c]}
*
* @param targetClass
* @return
* @see TypeAnnotationScanner
*/
public static List<Annotation> scanClass(Class<?> targetClass) {
return AnnotationScanner.TYPE_HIERARCHY.getAnnotationsIfSupport(targetClass);
}
/**
* <p>{@link Class}
* {@link #META_ANNOTATIONS}JDK,
* {@link Method#getAnnotations()}<br>
* 广
* <ul>
* <li></li>
* <li>{@code targetClass}</li>
* <li>/</li>
* </ul>
* /{@link Method#getAnnotations()}
*
* <p><br>
* X{@code A.class}/{@code B.class}X{@code C.class}
*
* <pre>
* A#X()[@a] -&gt; B#X()[@b] -&gt; C#X()[@c]
* </pre>
* {@code [@a, @b, @c]}
*
* @param method
* @return
* @see MethodAnnotationScanner
*/
public static List<Annotation> scanMethod(Method method) {
return AnnotationScanner.TYPE_HIERARCHY.getAnnotationsIfSupport(method);
}
/**
*
*
* @param annotation
* @param annotationField
* @param value
* @since 5.5.2
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static void setValue(Annotation annotation, String annotationField, Object value) {
final Map memberValues = (Map) ReflectUtil.getFieldValue(Proxy.getInvocationHandler(annotation), "memberValues");
memberValues.put(annotationField, value);
}
/**
*
*
* @param annotation
* @return
* @see SynthesizedAnnotationProxy#isProxyAnnotation(Class)
*/
public static boolean isSynthesizedAnnotation(Annotation annotation) {
return SynthesizedAnnotationProxy.isProxyAnnotation(annotation.getClass());
}
/**
*
*
* @param annotationEle
* @param annotationType Class
* @param <T>
* @return
* @since 5.7.23
*/
public static <T extends Annotation> T getAnnotationAlias(AnnotatedElement annotationEle, Class<T> annotationType) {
final T annotation = getAnnotation(annotationEle, annotationType);
return aggregatingFromAnnotation(annotation).synthesize(annotationType);
}
/**
*
*
* @param annotationType
* @param annotations
* @param <T>
* @return
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> T getSynthesizedAnnotation(Class<T> annotationType, Annotation... annotations) {
// TODO 缓存合成注解信息,避免重复解析
return Opt.ofNullable(annotations)
.filter(ArrayUtil::isNotEmpty)
.map(AnnotationUtil::aggregatingFromAnnotationWithMeta)
.map(a -> a.synthesize(annotationType))
.get();
}
/**
* <p>
* <ul>
* <li>;</li>
* <li>;</li>
* </ul>
*
* <p>
* {@code AnnotatedEle}ABC
* <pre>
* A -&gt; M3
* B -&gt; M1 -&gt; M2 -&gt; M3
* C -&gt; M2 -&gt; M3
* </pre>
* {@code annotationType}{@code M2}B
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @param <T>
* @return
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> T getSynthesizedAnnotation(AnnotatedElement annotatedEle, Class<T> annotationType) {
T target = annotatedEle.getAnnotation(annotationType);
if (ObjectUtil.isNotNull(target)) {
return target;
}
return AnnotationScanner.DIRECTLY
.getAnnotationsIfSupport(annotatedEle).stream()
.map(annotation -> getSynthesizedAnnotation(annotationType, annotation))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
/**
*
* <ul>
* <li>;</li>
* <li>;</li>
* </ul>
*
* <p>
* {@code AnnotatedEle}ABC
* <pre>
* A -&gt; M1 -&gt; M2
* B -&gt; M3 -&gt; M1 -&gt; M2
* C -&gt; M2
* </pre>
* {@code annotationType}{@code M1}AB
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param annotationType
* @param <T>
* @return
* @see SynthesizedAggregateAnnotation
*/
public static <T extends Annotation> List<T> getAllSynthesizedAnnotations(AnnotatedElement annotatedEle, Class<T> annotationType) {
return AnnotationScanner.DIRECTLY
.getAnnotationsIfSupport(annotatedEle).stream()
.map(annotation -> getSynthesizedAnnotation(annotationType, annotation))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
/**
*
*
* @param annotations
* @return
*/
public static SynthesizedAggregateAnnotation aggregatingFromAnnotation(Annotation... annotations) {
return new GenericSynthesizedAggregateAnnotation(Arrays.asList(annotations), AnnotationScanner.NOTHING);
}
/**
*
*
* @param annotations
* @return
*/
public static SynthesizedAggregateAnnotation aggregatingFromAnnotationWithMeta(Annotation... annotations) {
return new GenericSynthesizedAggregateAnnotation(Arrays.asList(annotations), AnnotationScanner.DIRECTLY_AND_META_ANNOTATION);
}
/**
* <br>
*
*
* @param method
*/
static boolean isAttributeMethod(Method method) {
return method.getParameterCount() == 0 && method.getReturnType() != void.class;
}
}

View File

@ -0,0 +1,63 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* {@link AnnotationAttribute}
*
* @author huangchengxing
*/
public class CacheableAnnotationAttribute implements AnnotationAttribute {
private boolean valueInvoked;
private Object value;
private boolean defaultValueInvoked;
private Object defaultValue;
private final Annotation annotation;
private final Method attribute;
public CacheableAnnotationAttribute(Annotation annotation, Method attribute) {
Assert.notNull(annotation, "annotation must not null");
Assert.notNull(attribute, "attribute must not null");
this.annotation = annotation;
this.attribute = attribute;
this.valueInvoked = false;
this.defaultValueInvoked = false;
}
@Override
public Annotation getAnnotation() {
return this.annotation;
}
@Override
public Method getAttribute() {
return this.attribute;
}
@Override
public Object getValue() {
if (!valueInvoked) {
valueInvoked = true;
value = ReflectUtil.invoke(annotation, attribute);
}
return value;
}
@Override
public boolean isValueEquivalentToDefaultValue() {
if (!defaultValueInvoked) {
defaultValue = attribute.getDefaultValue();
defaultValueInvoked = true;
}
return ObjectUtil.equals(getValue(), defaultValue);
}
}

View File

@ -0,0 +1,62 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.map.multi.RowKeyTable;
import aiyh.utils.tool.cn.hutool.core.map.multi.Table;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.util.Collection;
import java.util.Comparator;
/**
* <p>{@link SynthesizedAnnotationAttributeProcessor}
*
*
*
* <p>
*
* {@link Alias}{@link Link}
*
* @author huangchengxing
*/
public class CacheableSynthesizedAnnotationAttributeProcessor implements SynthesizedAnnotationAttributeProcessor {
private final Table<String, Class<?>, Object> valueCaches = new RowKeyTable<>();
private final Comparator<Hierarchical> annotationComparator;
/**
*
*
* @param annotationComparator
*/
public CacheableSynthesizedAnnotationAttributeProcessor(Comparator<Hierarchical> annotationComparator) {
Assert.notNull(annotationComparator, "annotationComparator must not null");
this.annotationComparator = annotationComparator;
}
/**
*
* {@link SynthesizedAnnotation#getVerticalDistance()}{@link SynthesizedAnnotation#getHorizontalDistance()}
*
*/
public CacheableSynthesizedAnnotationAttributeProcessor() {
this(Hierarchical.DEFAULT_HIERARCHICAL_COMPARATOR);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getAttributeValue(String attributeName, Class<T> attributeType, Collection<? extends SynthesizedAnnotation> synthesizedAnnotations) {
Object value = valueCaches.get(attributeName, attributeType);
// 此处理论上不可能出现缓存值为nul的情况
if (ObjectUtil.isNotNull(value)) {
return (T)value;
}
value = synthesizedAnnotations.stream()
.filter(ma -> ma.hasAttribute(attributeName, attributeType))
.min(annotationComparator)
.map(ma -> ma.getAttributeValue(attributeName))
.orElse(null);
valueCaches.put(attributeName, attributeType, value);
return (T)value;
}
}

View File

@ -0,0 +1,165 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.map.TableMap;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
/**
* JDKSpring<br>
* 使
*
* @author Succy, Looly
* @since 4.0.9
**/
public class CombinationAnnotationElement implements AnnotatedElement, Serializable {
private static final long serialVersionUID = 1L;
/**
* CombinationAnnotationElement
*
* @param element ClassMethodFieldConstructorReflectPermission
* @param predicate {@link Predicate#test(Object)}{@code true}
* @return CombinationAnnotationElement
* @since 5.8.0
*/
public static CombinationAnnotationElement of(AnnotatedElement element, Predicate<Annotation> predicate) {
return new CombinationAnnotationElement(element, predicate);
}
/**
*
*/
private Map<Class<? extends Annotation>, Annotation> annotationMap;
/**
*
*/
private Map<Class<? extends Annotation>, Annotation> declaredAnnotationMap;
/**
*
*/
private final Predicate<Annotation> predicate;
/**
*
*
* @param element ClassMethodFieldConstructorReflectPermission
*/
public CombinationAnnotationElement(AnnotatedElement element) {
this(element, null);
}
/**
*
*
* @param element ClassMethodFieldConstructorReflectPermission
* @param predicate {@link Predicate#test(Object)}{@code true}
* @since 5.8.0
*/
public CombinationAnnotationElement(AnnotatedElement element, Predicate<Annotation> predicate) {
this.predicate = predicate;
init(element);
}
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return annotationMap.containsKey(annotationClass);
}
@Override
@SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Annotation annotation = annotationMap.get(annotationClass);
return (annotation == null) ? null : (T) annotation;
}
@Override
public Annotation[] getAnnotations() {
final Collection<Annotation> annotations = this.annotationMap.values();
return annotations.toArray(new Annotation[0]);
}
@Override
public Annotation[] getDeclaredAnnotations() {
final Collection<Annotation> annotations = this.declaredAnnotationMap.values();
return annotations.toArray(new Annotation[0]);
}
/**
*
*
* @param element
*/
private void init(AnnotatedElement element) {
final Annotation[] declaredAnnotations = element.getDeclaredAnnotations();
this.declaredAnnotationMap = new TableMap<>();
parseDeclared(declaredAnnotations);
final Annotation[] annotations = element.getAnnotations();
if (Arrays.equals(declaredAnnotations, annotations)) {
this.annotationMap = this.declaredAnnotationMap;
} else {
this.annotationMap = new TableMap<>();
parse(annotations);
}
}
/**
*
*
* @param annotations Class, Method, Field
*/
private void parseDeclared(Annotation[] annotations) {
Class<? extends Annotation> annotationType;
// 直接注解
for (Annotation annotation : annotations) {
annotationType = annotation.annotationType();
// issue#I5FQGW@Gitee跳过元注解和已经处理过的注解防止递归调用
if (AnnotationUtil.isNotJdkMateAnnotation(annotationType)
&& false == declaredAnnotationMap.containsKey(annotationType)) {
if(test(annotation)){
declaredAnnotationMap.put(annotationType, annotation);
}
// 测试不通过的注解,不影响继续递归
parseDeclared(annotationType.getDeclaredAnnotations());
}
}
}
/**
*
*
* @param annotations Class, Method, Field
*/
private void parse(Annotation[] annotations) {
Class<? extends Annotation> annotationType;
for (Annotation annotation : annotations) {
annotationType = annotation.annotationType();
// issue#I5FQGW@Gitee跳过元注解和已经处理过的注解防止递归调用
if (AnnotationUtil.isNotJdkMateAnnotation(annotationType)
&& false == declaredAnnotationMap.containsKey(annotationType)) {
if(test(annotation)){
annotationMap.put(annotationType, annotation);
}
// 测试不通过的注解,不影响继续递归
parse(annotationType.getAnnotations());
}
}
}
/**
*
*
* @param annotation
* @return
*/
private boolean test(Annotation annotation) {
return null == this.predicate || this.predicate.test(annotation);
}
}

View File

@ -0,0 +1,35 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>{@link Link}{@link Alias}
*
* <b>{@link Link}{@link AliasFor}{@link MirrorFor}使</b>
*
* @author huangchengxing
* @see Link
* @see RelationType#FORCE_ALIAS_FOR
*/
@Link(type = RelationType.FORCE_ALIAS_FOR)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface ForceAliasFor {
/**
*
*
* @return
*/
@Link(annotation = Link.class, attribute = "annotation", type = RelationType.FORCE_ALIAS_FOR)
Class<? extends Annotation> annotation() default Annotation.class;
/**
* {@link #annotation()}
*
* @return
*/
@Link(annotation = Link.class, attribute = "attribute", type = RelationType.FORCE_ALIAS_FOR)
String attribute() default "";
}

View File

@ -0,0 +1,49 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
/**
*
* {@link #getValue()}{@link #linked}
*
* @author huangchengxing
* @see AliasAnnotationPostProcessor
* @see AliasLinkAnnotationPostProcessor
* @see RelationType#ALIAS_FOR
* @see RelationType#FORCE_ALIAS_FOR
*/
public class ForceAliasedAnnotationAttribute extends AbstractWrappedAnnotationAttribute {
protected ForceAliasedAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) {
super(origin, linked);
}
/**
* {@link #linked}{@link AnnotationAttribute#getValue()}
*
* @return {@link #linked}{@link AnnotationAttribute#getValue()}
*/
@Override
public Object getValue() {
return linked.getValue();
}
/**
* {@link #linked}{@link AnnotationAttribute#isValueEquivalentToDefaultValue()}
*
* @return {@link #linked}{@link AnnotationAttribute#isValueEquivalentToDefaultValue()}
*/
@Override
public boolean isValueEquivalentToDefaultValue() {
return linked.isValueEquivalentToDefaultValue();
}
/**
* {@link #linked}{@link AnnotationAttribute#getAttributeType()}
*
* @return {@link #linked}{@link AnnotationAttribute#getAttributeType()}
*/
@Override
public Class<?> getAttributeType() {
return linked.getAttributeType();
}
}

View File

@ -0,0 +1,318 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.annotation.scanner.AnnotationScanner;
import aiyh.utils.tool.cn.hutool.core.annotation.scanner.MetaAnnotationScanner;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.lang.Opt;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.*;
/**
* {@link SynthesizedAggregateAnnotation}
*
*
* <p>A{@link #annotationScanner}A
* ABBCAABC{@link GenericSynthesizedAggregateAnnotation}
* {@link AnnotatedElement}ABC
* {@link AnnotatedElement}
*
* <p>
* {@link SynthesizedAnnotationSelector}
* <br>
* 使{@link SynthesizedAnnotationSelector#NEAREST_AND_OLDEST_PRIORITY}
*
*
* <p>{@link SynthesizedAnnotationSelector}
* {@link MetaAnnotation}使{@link AliasAnnotationPostProcessor}
* <br>
* {@link Alias}{@link Link}
* <ul>
* <li>{@link AliasAnnotationPostProcessor}</li>
* <li>{@link MirrorLinkAnnotationPostProcessor}</li>
* <li>{@link AliasLinkAnnotationPostProcessor}</li>
* </ul>
*
*
* <p>{@link GenericSynthesizedAggregateAnnotation}{@link #getAttributeValue(String, Class)}
* {@link #synthesize(Class)}
* {@link Alias}{@link Link}
* {@link SynthesizedAnnotationAttributeProcessor}<br>
* {@link CacheableSynthesizedAnnotationAttributeProcessor}
*
*
* @author huangchengxing
* @see AnnotationUtil
* @see SynthesizedAnnotationProxy
* @see SynthesizedAnnotationSelector
* @see SynthesizedAnnotationAttributeProcessor
* @see SynthesizedAnnotationPostProcessor
* @see AnnotationSynthesizer
* @see AnnotationScanner
*/
public class GenericSynthesizedAggregateAnnotation
extends AbstractAnnotationSynthesizer<List<Annotation>>
implements SynthesizedAggregateAnnotation {
/**
*
*/
private final Object root;
/**
*
*/
private final int verticalDistance;
/**
*
*/
private final int horizontalDistance;
/**
*
*/
private final SynthesizedAnnotationAttributeProcessor attributeProcessor;
/**
*
* ,
*
*
* @param source
*/
public GenericSynthesizedAggregateAnnotation(Annotation... source) {
this(Arrays.asList(source), new MetaAnnotationScanner());
}
/**
*
*
*
*
* @param source
* @param annotationScanner
*/
public GenericSynthesizedAggregateAnnotation(List<Annotation> source, AnnotationScanner annotationScanner) {
this(
source, SynthesizedAnnotationSelector.NEAREST_AND_OLDEST_PRIORITY,
new CacheableSynthesizedAnnotationAttributeProcessor(),
Arrays.asList(
SynthesizedAnnotationPostProcessor.ALIAS_ANNOTATION_POST_PROCESSOR,
SynthesizedAnnotationPostProcessor.MIRROR_LINK_ANNOTATION_POST_PROCESSOR,
SynthesizedAnnotationPostProcessor.ALIAS_LINK_ANNOTATION_POST_PROCESSOR
),
annotationScanner
);
}
/**
*
*
* @param source
* @param annotationSelector
* @param attributeProcessor
* @param annotationPostProcessors
* @param annotationScanner
*/
public GenericSynthesizedAggregateAnnotation(
List<Annotation> source,
SynthesizedAnnotationSelector annotationSelector,
SynthesizedAnnotationAttributeProcessor attributeProcessor,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
this(
null, 0, 0,
source, annotationSelector, attributeProcessor, annotationPostProcessors, annotationScanner
);
}
/**
*
*
* @param root
* @param verticalDistance
* @param horizontalDistance
* @param source
* @param annotationSelector
* @param attributeProcessor
* @param annotationPostProcessors
* @param annotationScanner
*/
GenericSynthesizedAggregateAnnotation(
Object root, int verticalDistance, int horizontalDistance,
List<Annotation> source,
SynthesizedAnnotationSelector annotationSelector,
SynthesizedAnnotationAttributeProcessor attributeProcessor,
Collection<SynthesizedAnnotationPostProcessor> annotationPostProcessors,
AnnotationScanner annotationScanner) {
super(source, annotationSelector, annotationPostProcessors, annotationScanner);
Assert.notNull(attributeProcessor, "attributeProcessor must not null");
this.root = ObjectUtil.defaultIfNull(root, this);
this.verticalDistance = verticalDistance;
this.horizontalDistance = horizontalDistance;
this.attributeProcessor = attributeProcessor;
}
/**
*
*
* @return
*/
@Override
public Object getRoot() {
return root;
}
/**
*
*
* @return
*/
@Override
public int getVerticalDistance() {
return verticalDistance;
}
/**
*
*
* @return
*/
@Override
public int getHorizontalDistance() {
return horizontalDistance;
}
/**
* 广{@link #source}
*/
@Override
protected Map<Class<? extends Annotation>, SynthesizedAnnotation> loadAnnotations() {
Map<Class<? extends Annotation>, SynthesizedAnnotation> annotationMap = new LinkedHashMap<>();
// 根注解默认水平坐标为0根注解的元注解坐标从1开始
for (int i = 0; i < source.size(); i++) {
final Annotation sourceAnnotation = source.get(i);
Assert.isFalse(AnnotationUtil.isSynthesizedAnnotation(sourceAnnotation), "source [{}] has been synthesized");
annotationMap.put(sourceAnnotation.annotationType(), new MetaAnnotation(sourceAnnotation, sourceAnnotation, 0, i));
Assert.isTrue(
annotationScanner.support(sourceAnnotation.annotationType()),
"annotation scanner [{}] cannot support scan [{}]",
annotationScanner, sourceAnnotation.annotationType()
);
annotationScanner.scan(
(index, annotation) -> {
SynthesizedAnnotation oldAnnotation = annotationMap.get(annotation.annotationType());
SynthesizedAnnotation newAnnotation = new MetaAnnotation(sourceAnnotation, annotation, index + 1, annotationMap.size());
if (ObjectUtil.isNull(oldAnnotation)) {
annotationMap.put(annotation.annotationType(), newAnnotation);
} else {
annotationMap.put(annotation.annotationType(), annotationSelector.choose(oldAnnotation, newAnnotation));
}
},
sourceAnnotation.annotationType(), null
);
}
return annotationMap;
}
/**
*
*
* @return
*/
@Override
public SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor() {
return this.attributeProcessor;
}
/**
* {@link Alias}{@link Alias#value()}
* <p>
*
* @param attributeName
* @param attributeType
* @return
*/
@Override
public Object getAttributeValue(String attributeName, Class<?> attributeType) {
return attributeProcessor.getAttributeValue(attributeName, attributeType, synthesizedAnnotationMap.values());
}
/**
*
*
* @param annotationType
* @param <T>
* @return
*/
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
return Opt.ofNullable(annotationType)
.map(synthesizedAnnotationMap::get)
.map(SynthesizedAnnotation::getAnnotation)
.map(annotationType::cast)
.orElse(null);
}
/**
*
*
* @param annotationType
* @return
*/
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
return synthesizedAnnotationMap.containsKey(annotationType);
}
/**
*
*
* @return
*/
@Override
public Annotation[] getAnnotations() {
return synthesizedAnnotationMap.values().stream()
.map(SynthesizedAnnotation::getAnnotation)
.toArray(Annotation[]::new);
}
/**
* 使
*
* @param annotationType
* @return
* @see SynthesizedAnnotationProxy#create(Class, AnnotationAttributeValueProvider, SynthesizedAnnotation)
*/
@Override
public <T extends Annotation> T synthesize(Class<T> annotationType, SynthesizedAnnotation annotation) {
return SynthesizedAnnotationProxy.create(annotationType, this, annotation);
}
/**
* {@link #source}{@link #source}
*
* @author huangchengxing
*/
public static class MetaAnnotation extends GenericSynthesizedAnnotation<Annotation, Annotation> {
/**
*
*
* @param root
* @param annotation
* @param verticalDistance
* @param horizontalDistance
*/
protected MetaAnnotation(Annotation root, Annotation annotation, int verticalDistance, int horizontalDistance) {
super(root, annotation, verticalDistance, horizontalDistance);
}
}
}

View File

@ -0,0 +1,197 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Opt;
import aiyh.utils.tool.cn.hutool.core.util.ClassUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* {@link SynthesizedAnnotation}
*
* @param <R>
* @param <T>
* @author huangchengxing
*/
public class GenericSynthesizedAnnotation<R, T extends Annotation> implements SynthesizedAnnotation {
private final R root;
private final T annotation;
private final Map<String, AnnotationAttribute> attributeMethodCaches;
private final int verticalDistance;
private final int horizontalDistance;
/**
*
*
* @param root
* @param annotation
* @param verticalDistance
* @param horizontalDistance
*/
protected GenericSynthesizedAnnotation(
R root, T annotation, int verticalDistance, int horizontalDistance) {
this.root = root;
this.annotation = annotation;
this.verticalDistance = verticalDistance;
this.horizontalDistance = horizontalDistance;
this.attributeMethodCaches = new HashMap<>();
this.attributeMethodCaches.putAll(loadAttributeMethods());
}
/**
*
*
* @return
*/
protected Map<String, AnnotationAttribute> loadAttributeMethods() {
return Stream.of(ClassUtil.getDeclaredMethods(annotation.annotationType()))
.filter(AnnotationUtil::isAttributeMethod)
.collect(Collectors.toMap(Method::getName, method -> new CacheableAnnotationAttribute(annotation, method)));
}
/**
*
*
* @param attributeName
* @return
*/
public boolean hasAttribute(String attributeName) {
return attributeMethodCaches.containsKey(attributeName);
}
/**
*
*
* @param attributeName
* @param returnType
* @return
*/
@Override
public boolean hasAttribute(String attributeName, Class<?> returnType) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.filter(method -> ClassUtil.isAssignable(returnType, method.getAttributeType()))
.isPresent();
}
/**
*
*
* @return
*/
@Override
public Map<String, AnnotationAttribute> getAttributes() {
return this.attributeMethodCaches;
}
/**
*
*
* @param attributeName
* @param attribute
*/
@Override
public void setAttribute(String attributeName, AnnotationAttribute attribute) {
attributeMethodCaches.put(attributeName, attribute);
}
/**
*
*
* @param attributeName
* @param operator
*/
@Override
public void replaceAttribute(String attributeName, UnaryOperator<AnnotationAttribute> operator) {
AnnotationAttribute old = attributeMethodCaches.get(attributeName);
if (ObjectUtil.isNotNull(old)) {
attributeMethodCaches.put(attributeName, operator.apply(old));
}
}
/**
*
*
* @param attributeName
* @return
*/
@Override
public Object getAttributeValue(String attributeName) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.map(AnnotationAttribute::getValue)
.get();
}
/**
*
*
* @return
*/
@Override
public R getRoot() {
return root;
}
/**
*
*
* @return
*/
@Override
public T getAnnotation() {
return annotation;
}
/**
*
*
*
* @return
*/
@Override
public int getVerticalDistance() {
return verticalDistance;
}
/**
*
*
*
* @return
*/
@Override
public int getHorizontalDistance() {
return horizontalDistance;
}
/**
*
*
* @return
*/
@Override
public Class<? extends Annotation> annotationType() {
return annotation.annotationType();
}
/**
*
*
* @param attributeName
* @param attributeType
* @return
*/
@Override
public Object getAttributeValue(String attributeName, Class<?> attributeType) {
return Opt.ofNullable(attributeMethodCaches.get(attributeName))
.filter(method -> ClassUtil.isAssignable(attributeType, method.getAttributeType()))
.map(AnnotationAttribute::getValue)
.get();
}
}

View File

@ -0,0 +1,155 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.util.Comparator;
/**
* <p>
*
* <p>{@link #getVerticalDistance()}{@link #getHorizontalDistance()}
* <br>
* {@link #getRoot()}
* {@link #DEFAULT_HIERARCHICAL_COMPARATOR}<br>
* {@link #getRoot()}
*
* <p>{@link Selector}{@link Hierarchical}
*
* <ul>
* <li>{@link Selector#NEAREST_AND_OLDEST_PRIORITY}: </li>
* <li>{@link Selector#NEAREST_AND_NEWEST_PRIORITY}: </li>
* <li>{@link Selector#FARTHEST_AND_OLDEST_PRIORITY}: </li>
* <li>{@link Selector#FARTHEST_AND_NEWEST_PRIORITY}: </li>
* </ul>
*
* @author huangchengxing
*/
public interface Hierarchical extends Comparable<Hierarchical> {
// ====================== compare ======================
/**
* {@link #getHorizontalDistance()}{@link #getVerticalDistance()}
*/
Comparator<Hierarchical> DEFAULT_HIERARCHICAL_COMPARATOR = Comparator
.comparing(Hierarchical::getVerticalDistance)
.thenComparing(Hierarchical::getHorizontalDistance);
/**
* {@link #getVerticalDistance()}{@link #getHorizontalDistance()}
*
* @param o {@link SynthesizedAnnotation}
* @return
*/
@Override
default int compareTo(Hierarchical o) {
return DEFAULT_HIERARCHICAL_COMPARATOR.compare(this, o);
}
// ====================== hierarchical ======================
/**
* {@code (0, 0)}
*
*
* @return
*/
Object getRoot();
/**
*
*
*
* @return
*/
int getVerticalDistance();
/**
*
* {@link #getVerticalDistance()}
*
*
* @return
*/
int getHorizontalDistance();
// ====================== selector ======================
/**
* {@link Hierarchical}{@link Hierarchical}
*/
@FunctionalInterface
interface Selector {
/**
*
*/
Selector NEAREST_AND_OLDEST_PRIORITY = new NearestAndOldestPrioritySelector();
/**
*
*/
Selector NEAREST_AND_NEWEST_PRIORITY = new NearestAndNewestPrioritySelector();
/**
*
*/
Selector FARTHEST_AND_OLDEST_PRIORITY = new FarthestAndOldestPrioritySelector();
/**
*
*/
Selector FARTHEST_AND_NEWEST_PRIORITY = new FarthestAndNewestPrioritySelector();
/**
*
*
* @param <T>
* @param prev
* @param next
* @return
*/
<T extends Hierarchical> T choose(T prev, T next);
/**
*
*/
class NearestAndOldestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() < oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
/**
*
*/
class NearestAndNewestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() <= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
/**
*
*/
class FarthestAndOldestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() > oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
/**
*
*/
class FarthestAndNewestPrioritySelector implements Selector {
@Override
public <T extends Hierarchical> T choose(T oldAnnotation, T newAnnotation) {
return newAnnotation.getVerticalDistance() >= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation;
}
}
}
}

View File

@ -0,0 +1,49 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>
* {@link SynthesizedAggregateAnnotation}<br>
*
* <p>{@link MirrorFor}{@link ForceAliasFor}{@link AliasFor}
* 使{@link Link}
* {@link Link}{@link Link}
*
*
* <b>{@link Alias}</b>
*
* @author huangchengxing
* @see SynthesizedAggregateAnnotation
* @see RelationType
* @see AliasFor
* @see MirrorFor
* @see ForceAliasFor
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Link {
/**
*
*
* @return
*/
Class<? extends Annotation> annotation() default Annotation.class;
/**
* {@link #annotation()}
*
* @return
*/
String attribute() default "";
/**
* {@link #attribute()}
*
* @return
*/
RelationType type() default RelationType.MIRROR_FOR;
}

View File

@ -0,0 +1,42 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.*;
/**
* <p>{@link Link}<br>
*
* <ul>
* <li>{@code MIRROR_FOR}{@link Link}</li>
* <li></li>
* <li></li>
* <li></li>
* </ul>
* <b>{@link Link}{@link ForceAliasFor}{@link AliasFor}使</b>
*
* @author huangchengxing
* @see Link
* @see RelationType#MIRROR_FOR
*/
@Link(type = RelationType.MIRROR_FOR)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface MirrorFor {
/**
*
*
* @return
*/
@Link(annotation = Link.class, attribute = "annotation", type = RelationType.FORCE_ALIAS_FOR)
Class<? extends Annotation> annotation() default Annotation.class;
/**
* {@link #annotation()}
*
* @return
*/
@Link(annotation = Link.class, attribute = "attribute", type = RelationType.FORCE_ALIAS_FOR)
String attribute() default "";
}

View File

@ -0,0 +1,132 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.text.CharSequenceUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
/**
* <p>{@link Link}{@link Link#type()}{@link RelationType#MIRROR_FOR}<br>
* {@link Link}{@link Link}
* {@link MirroredAnnotationAttribute}
*
* @author huangchengxing
* @see RelationType#MIRROR_FOR
* @see MirroredAnnotationAttribute
*/
public class MirrorLinkAnnotationPostProcessor extends AbstractLinkAnnotationPostProcessor {
private static final RelationType[] PROCESSED_RELATION_TYPES = new RelationType[]{ RelationType.MIRROR_FOR };
@Override
public int order() {
return Integer.MIN_VALUE + 1;
}
/**
* {@link Link#type()}{@link RelationType#MIRROR_FOR}
*
* @return {@link RelationType#MIRROR_FOR}
*/
@Override
protected RelationType[] processTypes() {
return PROCESSED_RELATION_TYPES;
}
/**
* {@link MirroredAnnotationAttribute}
* 使{@link MirroredAnnotationAttribute}{@link AnnotationAttribute}
*
* @param synthesizer
* @param annotation {@code originalAttribute}{@link Link}
* @param originalAnnotation {@link SynthesizedAnnotation}
* @param originalAttribute {@code originalAnnotation}
* @param linkedAnnotation {@link Link}
* @param linkedAttribute {@link Link}{@code originalAnnotation}
*/
@Override
protected void processLinkedAttribute(
AnnotationSynthesizer synthesizer, Link annotation,
SynthesizedAnnotation originalAnnotation, AnnotationAttribute originalAttribute,
SynthesizedAnnotation linkedAnnotation, AnnotationAttribute linkedAttribute) {
// 镜像属性必然成对出现,因此此处必定存在三种情况:
// 1.两属性都不为镜像属性,此时继续进行后续处理;
// 2.两属性都为镜像属性,并且指向对方,此时无需后续处理;
// 3.两属性仅有任意一属性为镜像属性,此时镜像属性必然未指向当前原始属性,此时应该抛出异常;
if (originalAttribute instanceof MirroredAnnotationAttribute
|| linkedAttribute instanceof MirroredAnnotationAttribute) {
checkMirrored(originalAttribute, linkedAttribute);
return;
}
// 校验镜像关系
checkMirrorRelation(annotation, originalAttribute, linkedAttribute);
// 包装这一对镜像属性,并替换原注解中的对应属性
final AnnotationAttribute mirroredOriginalAttribute = new MirroredAnnotationAttribute(originalAttribute, linkedAttribute);
originalAnnotation.setAttribute(originalAttribute.getAttributeName(), mirroredOriginalAttribute);
final AnnotationAttribute mirroredTargetAttribute = new MirroredAnnotationAttribute(linkedAttribute, originalAttribute);
linkedAnnotation.setAttribute(annotation.attribute(), mirroredTargetAttribute);
}
/**
*
*/
private void checkMirrored(AnnotationAttribute original, AnnotationAttribute mirror) {
final boolean originalAttributeMirrored = original instanceof MirroredAnnotationAttribute;
final boolean mirrorAttributeMirrored = mirror instanceof MirroredAnnotationAttribute;
// 校验通过
final boolean passed = originalAttributeMirrored && mirrorAttributeMirrored
&& ObjectUtil.equals(((MirroredAnnotationAttribute)original).getLinked(), ((MirroredAnnotationAttribute)mirror).getOriginal());
if (passed) {
return;
}
// 校验失败,拼装异常信息用于抛出异常
String errorMsg;
// 原始字段已经跟其他字段形成镜像
if (originalAttributeMirrored && !mirrorAttributeMirrored) {
errorMsg = CharSequenceUtil.format(
"attribute [{}] cannot mirror for [{}], because it's already mirrored for [{}]",
original.getAttribute(), mirror.getAttribute(), ((MirroredAnnotationAttribute)original).getLinked()
);
}
// 镜像字段已经跟其他字段形成镜像
else if (!originalAttributeMirrored && mirrorAttributeMirrored) {
errorMsg = CharSequenceUtil.format(
"attribute [{}] cannot mirror for [{}], because it's already mirrored for [{}]",
mirror.getAttribute(), original.getAttribute(), ((MirroredAnnotationAttribute)mirror).getLinked()
);
}
// 两者都形成了镜像,但是都未指向对方,理论上不会存在该情况
else {
errorMsg = CharSequenceUtil.format(
"attribute [{}] cannot mirror for [{}], because [{}] already mirrored for [{}] and [{}] already mirrored for [{}]",
mirror.getAttribute(), original.getAttribute(),
mirror.getAttribute(), ((MirroredAnnotationAttribute)mirror).getLinked(),
original.getAttribute(), ((MirroredAnnotationAttribute)original).getLinked()
);
}
throw new IllegalArgumentException(errorMsg);
}
/**
*
*/
private void checkMirrorRelation(Link annotation, AnnotationAttribute original, AnnotationAttribute mirror) {
// 镜像属性必须存在
checkLinkedAttributeNotNull(original, mirror, annotation);
// 镜像属性返回值必须一致
checkAttributeType(original, mirror);
// 镜像属性上必须存在对应的注解
final Link mirrorAttributeAnnotation = getLinkAnnotation(mirror, RelationType.MIRROR_FOR);
Assert.isTrue(
ObjectUtil.isNotNull(mirrorAttributeAnnotation) && RelationType.MIRROR_FOR.equals(mirrorAttributeAnnotation.type()),
"mirror attribute [{}] of original attribute [{}] must marked by @Link, and also @LinkType.type() must is [{}]",
mirror.getAttribute(), original.getAttribute(), RelationType.MIRROR_FOR
);
checkLinkedSelf(original, mirror);
}
}

View File

@ -0,0 +1,48 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
/**
* {@link RelationType#MIRROR_FOR}
*
* @author huangchengxing
* @see MirrorLinkAnnotationPostProcessor
* @see RelationType#MIRROR_FOR
*/
public class MirroredAnnotationAttribute extends AbstractWrappedAnnotationAttribute {
public MirroredAnnotationAttribute(AnnotationAttribute origin, AnnotationAttribute linked) {
super(origin, linked);
}
@Override
public Object getValue() {
final boolean originIsDefault = original.isValueEquivalentToDefaultValue();
final boolean targetIsDefault = linked.isValueEquivalentToDefaultValue();
final Object originValue = original.getValue();
final Object targetValue = linked.getValue();
// 都为默认值,或都为非默认值时,两方法的返回值必须相等
if (originIsDefault == targetIsDefault) {
Assert.equals(
originValue, targetValue,
"the values of attributes [{}] and [{}] that mirror each other are different: [{}] <==> [{}]",
original.getAttribute(), linked.getAttribute(), originValue, targetValue
);
return originValue;
}
// 两者有一者不为默认值时,优先返回非默认值
return originIsDefault ? targetValue : originValue;
}
/**
* {@link #original}{@link #linked}{@code true}
*
* @return
*/
@Override
public boolean isValueEquivalentToDefaultValue() {
return original.isValueEquivalentToDefaultValue() && linked.isValueEquivalentToDefaultValue();
}
}

View File

@ -0,0 +1,21 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 使BeanBeanMap<br>
* setXXXgetXXX
*
* @author Looly
* @since 5.4.2
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface PropIgnore {
}

View File

@ -0,0 +1,50 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
/**
* <p> <br>
* {@link Link}{@link Link}
* {@link SynthesizedAggregateAnnotation}<br>
* {@link Link#type()}{@link SynthesizedAggregateAnnotation}
*
* <p>
* <ol>
* <li>{@link Alias}</li>
* <li>{@link Link}{@link Link#type()}{@link #MIRROR_FOR}</li>
* <li>{@link Link}{@link Link#type()}{@link #FORCE_ALIAS_FOR}</li>
* <li>{@link Link}{@link Link#type()}{@link #ALIAS_FOR}</li>
* </ol>
*
* @author huangchengxing
* @see SynthesizedAggregateAnnotation
* @see Link
*/
public enum RelationType {
/**
* <p><br>
*
* <ul>
* <li>{@code MIRROR_FOR}{@link Link}</li>
* <li></li>
* <li></li>
* <li></li>
* </ul>
*/
MIRROR_FOR,
/**
* <p>
* <ul>
* <li></li>
* <li></li>
* </ul>
*/
ALIAS_FOR,
/**
* <p>{@link Alias}
*
*/
FORCE_ALIAS_FOR;
}

View File

@ -0,0 +1,102 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
/**
* <p>
*
*
* <p>
* 使{@link SynthesizedAnnotationSelector}
* {@link SynthesizedAnnotation}
* {@link SynthesizedAggregateAnnotation}<br>
* {@link SynthesizedAnnotationSelector}
*
*
* <p>
* {@link SynthesizedAnnotationPostProcessor}
*
* {@link Link}<br>
* {@link SynthesizedAnnotationPostProcessor}
*
*
* <p>{@link #synthesize(Class)}
*
* {@link SynthesizedAnnotationAttributeProcessor}
* <br>
* {@link SynthesizedAnnotationAttributeProcessor}
*
*
* @author huangchengxing
* @see AnnotationSynthesizer
* @see SynthesizedAnnotation
* @see SynthesizedAnnotationSelector
* @see SynthesizedAnnotationAttributeProcessor
* @see SynthesizedAnnotationPostProcessor
* @see GenericSynthesizedAggregateAnnotation
*/
public interface SynthesizedAggregateAnnotation extends AggregateAnnotation, Hierarchical, AnnotationSynthesizer, AnnotationAttributeValueProvider {
// ================== hierarchical ==================
/**
* {@link #getRoot()}
* 0
*
* @return {@link #getRoot()}
*/
@Override
default int getVerticalDistance() {
return 0;
}
/**
* {@link #getRoot()}
* 0
*
* @return {@link #getRoot()}
*/
@Override
default int getHorizontalDistance() {
return 0;
}
// ================== synthesize ==================
/**
*
*
* @param annotationType
* @param <T>
* @return
*/
<T extends Annotation> T getAnnotation(Class<T> annotationType);
/**
*
*
* @return
*/
SynthesizedAnnotationAttributeProcessor getAnnotationAttributeProcessor();
/**
*
*
* @return
*/
@Override
default Class<? extends Annotation> annotationType() {
return this.getClass();
}
/**
*
*
* @param attributeName
* @param attributeType
* @return
*/
@Override
Object getAttributeValue(String attributeName, Class<?> attributeType);
}

View File

@ -0,0 +1,96 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.function.UnaryOperator;
/**
* <p>{@link SynthesizedAggregateAnnotation}<br>
* 使{@link #DEFAULT_HIERARCHICAL_COMPARATOR}
* {@link #getVerticalDistance()}{@link #getHorizontalDistance()}
* 使
*
* @author huangchengxing
* @see SynthesizedAggregateAnnotation
*/
public interface SynthesizedAnnotation extends Annotation, Hierarchical, AnnotationAttributeValueProvider {
/**
*
*
* @return
*/
Annotation getAnnotation();
/**
*
*
*
* @return
*/
@Override
int getVerticalDistance();
/**
*
*
*
* @return
*/
@Override
int getHorizontalDistance();
/**
*
*
* @param attributeName
* @param returnType
* @return
*/
boolean hasAttribute(String attributeName, Class<?> returnType);
/**
*
*
* @return
*/
Map<String, AnnotationAttribute> getAttributes();
/**
*
*
* @param attributes
*/
default void setAttributes(Map<String, AnnotationAttribute> attributes) {
if (CollUtil.isNotEmpty(attributes)) {
attributes.forEach(this::setAttribute);
}
}
/**
*
*
* @param attributeName
* @param attribute
*/
void setAttribute(String attributeName, AnnotationAttribute attribute);
/**
*
*
* @param attributeName
* @param operator
*/
void replaceAttribute(String attributeName, UnaryOperator<AnnotationAttribute> operator);
/**
*
*
* @param attributeName
* @return
*/
Object getAttributeValue(String attributeName);
}

View File

@ -0,0 +1,24 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.util.Collection;
/**
* {@link SynthesizedAggregateAnnotation}
*
* @author huangchengxing
*/
@FunctionalInterface
public interface SynthesizedAnnotationAttributeProcessor {
/**
*
*
* @param attributeName
* @param attributeType
* @param synthesizedAnnotations
* @param <R>
* @return
*/
<R> R getAttributeValue(String attributeName, Class<R> attributeType, Collection<? extends SynthesizedAnnotation> synthesizedAnnotations);
}

View File

@ -0,0 +1,71 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.comparator.CompareUtil;
import java.util.Comparator;
/**
* <p>{@link SynthesizedAggregateAnnotation}
* {@link SynthesizedAnnotation}<br>
* {@link SynthesizedAnnotationPostProcessor}{@link #order()}
*
*
* <p>
* <ul>
* <li>{@link AliasAnnotationPostProcessor}</li>
* <li>{@link MirrorLinkAnnotationPostProcessor}</li>
* <li>{@link AliasLinkAnnotationPostProcessor}</li>
* <li></li>
* </ul>
*
* @author huangchengxing
* @see AliasAnnotationPostProcessor
* @see MirrorLinkAnnotationPostProcessor
* @see AliasLinkAnnotationPostProcessor
*/
public interface SynthesizedAnnotationPostProcessor extends Comparable<SynthesizedAnnotationPostProcessor> {
/**
* {@link Alias}
*/
AliasAnnotationPostProcessor ALIAS_ANNOTATION_POST_PROCESSOR = new AliasAnnotationPostProcessor();
/**
* {@link Link}
*/
MirrorLinkAnnotationPostProcessor MIRROR_LINK_ANNOTATION_POST_PROCESSOR = new MirrorLinkAnnotationPostProcessor();
/**
* {@link Link}
*/
AliasLinkAnnotationPostProcessor ALIAS_LINK_ANNOTATION_POST_PROCESSOR = new AliasLinkAnnotationPostProcessor();
/**
*
*
* @return
*/
default int order() {
return Integer.MAX_VALUE;
}
/**
* {@link #order()}
*
* @param o
* @return
*/
@Override
default int compareTo(SynthesizedAnnotationPostProcessor o) {
return CompareUtil.compare(this, o, Comparator.comparing(SynthesizedAnnotationPostProcessor::order));
}
/**
*
*
* @param synthesizedAnnotation
* @param synthesizer
*/
void process(SynthesizedAnnotation synthesizedAnnotation, AnnotationSynthesizer synthesizer);
}

View File

@ -0,0 +1,160 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.lang.Opt;
import aiyh.utils.tool.cn.hutool.core.text.CharSequenceUtil;
import aiyh.utils.tool.cn.hutool.core.util.ClassUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* {@link SynthesizedAnnotation}
*
* @author huangchengxing
* @see SynthesizedAnnotation
* @see AnnotationAttributeValueProvider
*/
public class SynthesizedAnnotationProxy implements InvocationHandler {
private final AnnotationAttributeValueProvider annotationAttributeValueProvider;
private final SynthesizedAnnotation annotation;
private final Map<String, BiFunction<Method, Object[], Object>> methods;
/**
* {@link SyntheticProxyAnnotation}
*
* @param <T>
* @param annotationType
* @param annotationAttributeValueProvider
* @param annotation
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends Annotation> T create(
Class<T> annotationType,
AnnotationAttributeValueProvider annotationAttributeValueProvider,
SynthesizedAnnotation annotation) {
if (ObjectUtil.isNull(annotation)) {
return null;
}
final SynthesizedAnnotationProxy proxyHandler = new SynthesizedAnnotationProxy(annotationAttributeValueProvider, annotation);
if (ObjectUtil.isNull(annotation)) {
return null;
}
return (T) Proxy.newProxyInstance(
annotationType.getClassLoader(),
new Class[]{annotationType, SyntheticProxyAnnotation.class},
proxyHandler
);
}
/**
* {@link SyntheticProxyAnnotation}
*
* @param <T>
* @param annotationType
* @param annotation
* @return
*/
public static <T extends Annotation> T create(
Class<T> annotationType, SynthesizedAnnotation annotation) {
return create(annotationType, annotation, annotation);
}
/**
* {@code SynthesizedAnnotationProxy}
*
* @param annotationType
* @return
*/
public static boolean isProxyAnnotation(Class<?> annotationType) {
return ClassUtil.isAssignable(SyntheticProxyAnnotation.class, annotationType);
}
SynthesizedAnnotationProxy(AnnotationAttributeValueProvider annotationAttributeValueProvider, SynthesizedAnnotation annotation) {
Assert.notNull(annotationAttributeValueProvider, "annotationAttributeValueProvider must not null");
Assert.notNull(annotation, "annotation must not null");
this.annotationAttributeValueProvider = annotationAttributeValueProvider;
this.annotation = annotation;
this.methods = new HashMap<>(9);
loadMethods();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return Opt.ofNullable(methods.get(method.getName()))
.map(m -> m.apply(method, args))
.orElseGet(() -> ReflectUtil.invoke(this, method, args));
}
// ========================= 代理方法 =========================
void loadMethods() {
methods.put("toString", (method, args) -> proxyToString());
methods.put("hashCode", (method, args) -> proxyHashCode());
methods.put("getSynthesizedAnnotation", (method, args) -> proxyGetSynthesizedAnnotation());
methods.put("getRoot", (method, args) -> annotation.getRoot());
methods.put("getVerticalDistance", (method, args) -> annotation.getVerticalDistance());
methods.put("getHorizontalDistance", (method, args) -> annotation.getHorizontalDistance());
methods.put("hasAttribute", (method, args) -> annotation.hasAttribute((String) args[0], (Class<?>) args[1]));
methods.put("getAttributes", (method, args) -> annotation.getAttributes());
methods.put("setAttribute", (method, args) -> {
throw new UnsupportedOperationException("proxied annotation can not reset attributes");
});
methods.put("getAttributeValue", (method, args) -> annotation.getAttributeValue((String) args[0]));
methods.put("annotationType", (method, args) -> annotation.annotationType());
for (final Method declaredMethod : ClassUtil.getDeclaredMethods(annotation.getAnnotation().annotationType())) {
methods.put(declaredMethod.getName(), (method, args) -> proxyAttributeValue(method));
}
}
private String proxyToString() {
final String attributes = Stream.of(ClassUtil.getDeclaredMethods(annotation.getAnnotation().annotationType()))
.filter(AnnotationUtil::isAttributeMethod)
.map(method -> CharSequenceUtil.format(
"{}={}", method.getName(), proxyAttributeValue(method))
)
.collect(Collectors.joining(", "));
return CharSequenceUtil.format("@{}({})", annotation.annotationType().getName(), attributes);
}
private int proxyHashCode() {
return Objects.hash(annotationAttributeValueProvider, annotation);
}
private Object proxyGetSynthesizedAnnotation() {
return annotation;
}
private Object proxyAttributeValue(Method attributeMethod) {
return annotationAttributeValueProvider.getAttributeValue(attributeMethod.getName(), attributeMethod.getReturnType());
}
/**
*
*
* @author huangchengxing
*/
interface SyntheticProxyAnnotation extends SynthesizedAnnotation {
/**
*
*
* @return
*/
SynthesizedAnnotation getSynthesizedAnnotation();
}
}

View File

@ -0,0 +1,82 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
/**
* <br>
* {@link SynthesizedAggregateAnnotation}
*
* @author huangchengxing
*/
@FunctionalInterface
public interface SynthesizedAnnotationSelector {
/**
*
*/
SynthesizedAnnotationSelector NEAREST_AND_OLDEST_PRIORITY = new NearestAndOldestPrioritySelector();
/**
*
*/
SynthesizedAnnotationSelector NEAREST_AND_NEWEST_PRIORITY = new NearestAndNewestPrioritySelector();
/**
*
*/
SynthesizedAnnotationSelector FARTHEST_AND_OLDEST_PRIORITY = new FarthestAndOldestPrioritySelector();
/**
*
*/
SynthesizedAnnotationSelector FARTHEST_AND_NEWEST_PRIORITY = new FarthestAndNewestPrioritySelector();
/**
*
*
* @param <T>
* @param oldAnnotation
* @param newAnnotation
* @return
*/
<T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation);
/**
*
*/
class NearestAndOldestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.NEAREST_AND_OLDEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
/**
*
*/
class NearestAndNewestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.NEAREST_AND_NEWEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
/**
*
*/
class FarthestAndOldestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.FARTHEST_AND_OLDEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
/**
*
*/
class FarthestAndNewestPrioritySelector implements SynthesizedAnnotationSelector {
@Override
public <T extends SynthesizedAnnotation> T choose(T oldAnnotation, T newAnnotation) {
return Hierarchical.Selector.FARTHEST_AND_NEWEST_PRIORITY.choose(oldAnnotation, newAnnotation);
}
}
}

View File

@ -0,0 +1,125 @@
package aiyh.utils.tool.cn.hutool.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
/**
* <p>{@link AnnotationAttribute}
*
* 使<br>
* {@link #getValue()}{@link #getOriginal()}
* {@link AnnotationAttribute}
*
* <p>
* abab{@link MirroredAnnotationAttribute}
* cacab{@link AliasedAnnotationAttribute}<br>
* ab{@link AliasedAnnotationAttribute}
* c{@link MirroredAnnotationAttribute}
*
* <p>{@link AnnotationAttribute}
*
*
*
* @author huangchengxing
* @see AnnotationAttribute
* @see ForceAliasedAnnotationAttribute
* @see AliasedAnnotationAttribute
* @see MirroredAnnotationAttribute
*/
public interface WrappedAnnotationAttribute extends AnnotationAttribute {
// =========================== 新增方法 ===========================
/**
* {@link AnnotationAttribute}{@link AnnotationAttribute}
*
* @return {@link AnnotationAttribute}
*/
AnnotationAttribute getOriginal();
/**
* {@link AnnotationAttribute}
*
* @return {@link AnnotationAttribute}
*/
AnnotationAttribute getNonWrappedOriginal();
/**
* {@link #getOriginal()}{@link AnnotationAttribute}{@link AnnotationAttribute}
*
* @return
*/
AnnotationAttribute getLinked();
/**
*
*
* @return
*/
Collection<AnnotationAttribute> getAllLinkedNonWrappedAttributes();
// =========================== 代理实现 ===========================
/**
*
*
* @return
*/
@Override
default Annotation getAnnotation() {
return getOriginal().getAnnotation();
}
/**
*
*
* @return
*/
@Override
default Method getAttribute() {
return getOriginal().getAttribute();
}
/**
* <br>
* {@link #getOriginal()}{@link #getLinked()}
* {@code true}
*
* @return
*/
@Override
boolean isValueEquivalentToDefaultValue();
/**
*
*
* @return
*/
@Override
default Class<?> getAttributeType() {
return getOriginal().getAttributeType();
}
/**
*
*
* @param annotationType
* @return
*/
@Override
default <T extends Annotation> T getAnnotation(Class<T> annotationType) {
return getOriginal().getAnnotation(annotationType);
}
/**
* {@link WrappedAnnotationAttribute}
*
* @return boolean
*/
@Override
default boolean isWrapped() {
return true;
}
}

View File

@ -0,0 +1,7 @@
/**
*
*
* @author looly
*
*/
package aiyh.utils.tool.cn.hutool.core.annotation;

View File

@ -0,0 +1,288 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.annotation.AnnotationUtil;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/**
* {@link AnnotationScanner}
*
* @author huangchengxing
*/
public abstract class AbstractTypeAnnotationScanner<T extends AbstractTypeAnnotationScanner<T>> implements AnnotationScanner {
/**
*
*/
private boolean includeSuperClass;
/**
*
*/
private boolean includeInterfaces;
/**
*
*/
private Predicate<Class<?>> filter;
/**
*
*/
private final Set<Class<?>> excludeTypes;
/**
*
*/
private final List<UnaryOperator<Class<?>>> converters;
/**
*
*/
private boolean hasConverters;
/**
*
*/
private final T typedThis;
/**
*
*
* @param includeSuperClass
* @param includeInterfaces
* @param filter
* @param excludeTypes
*/
@SuppressWarnings("unchecked")
protected AbstractTypeAnnotationScanner(boolean includeSuperClass, boolean includeInterfaces, Predicate<Class<?>> filter, Set<Class<?>> excludeTypes) {
Assert.notNull(filter, "filter must not null");
Assert.notNull(excludeTypes, "excludeTypes must not null");
this.includeSuperClass = includeSuperClass;
this.includeInterfaces = includeInterfaces;
this.filter = filter;
this.excludeTypes = excludeTypes;
this.converters = new ArrayList<>();
this.typedThis = (T) this;
}
/**
*
*
* @return
*/
public boolean isIncludeSuperClass() {
return includeSuperClass;
}
/**
*
*
* @return
*/
public boolean isIncludeInterfaces() {
return includeInterfaces;
}
/**
*
*
* @param filter
* @return
*/
public T setFilter(Predicate<Class<?>> filter) {
Assert.notNull(filter, "filter must not null");
this.filter = filter;
return typedThis;
}
/**
*
*
* @param excludeTypes
* @return
*/
public T addExcludeTypes(Class<?>... excludeTypes) {
CollUtil.addAll(this.excludeTypes, excludeTypes);
return typedThis;
}
/**
*
*
* @param converter
* @return
* @see JdkProxyClassConverter
*/
public T addConverters(UnaryOperator<Class<?>> converter) {
Assert.notNull(converter, "converter must not null");
this.converters.add(converter);
if (!this.hasConverters) {
this.hasConverters = CollUtil.isNotEmpty(this.converters);
}
return typedThis;
}
/**
*
*
* @param includeSuperClass
* @return
*/
protected T setIncludeSuperClass(boolean includeSuperClass) {
this.includeSuperClass = includeSuperClass;
return typedThis;
}
/**
*
*
* @param includeInterfaces
* @return
*/
protected T setIncludeInterfaces(boolean includeInterfaces) {
this.includeInterfaces = includeInterfaces;
return typedThis;
}
/**
* 广/
*
* @param consumer
* @param annotatedEle
* @param filter
*/
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
filter = ObjectUtil.defaultIfNull(filter, a -> annotation -> true);
final Class<?> sourceClass = getClassFormAnnotatedElement(annotatedEle);
final Deque<List<Class<?>>> classDeque = CollUtil.newLinkedList(CollUtil.newArrayList(sourceClass));
final Set<Class<?>> accessedTypes = new LinkedHashSet<>();
int index = 0;
while (!classDeque.isEmpty()) {
final List<Class<?>> currClassQueue = classDeque.removeFirst();
final List<Class<?>> nextClassQueue = new ArrayList<>();
for (Class<?> targetClass : currClassQueue) {
targetClass = convert(targetClass);
// 过滤不需要处理的类
if (isNotNeedProcess(accessedTypes, targetClass)) {
continue;
}
accessedTypes.add(targetClass);
// 扫描父类
scanSuperClassIfNecessary(nextClassQueue, targetClass);
// 扫描接口
scanInterfaceIfNecessary(nextClassQueue, targetClass);
// 处理层级索引和注解
final Annotation[] targetAnnotations = getAnnotationsFromTargetClass(annotatedEle, index, targetClass);
for (final Annotation annotation : targetAnnotations) {
if (AnnotationUtil.isNotJdkMateAnnotation(annotation.annotationType()) && filter.test(annotation)) {
consumer.accept(index, annotation);
}
}
index++;
}
if (CollUtil.isNotEmpty(nextClassQueue)) {
classDeque.addLast(nextClassQueue);
}
}
}
/**
*
*
* @param annotatedElement
* @return
*/
protected abstract Class<?> getClassFormAnnotatedElement(AnnotatedElement annotatedElement);
/**
*
*
* @param source
* @param index
* @param targetClass
* @return
*/
protected abstract Annotation[] getAnnotationsFromTargetClass(AnnotatedElement source, int index, Class<?> targetClass);
/**
*
*
* @param accessedTypes 访
* @param targetClass
* @return
*/
protected boolean isNotNeedProcess(Set<Class<?>> accessedTypes, Class<?> targetClass) {
return ObjectUtil.isNull(targetClass)
|| accessedTypes.contains(targetClass)
|| excludeTypes.contains(targetClass)
|| filter.negate().test(targetClass);
}
/**
* {@link #includeInterfaces}{@code true}nextClasses
*
* @param nextClasses
* @param targetClass
*/
protected void scanInterfaceIfNecessary(List<Class<?>> nextClasses, Class<?> targetClass) {
if (includeInterfaces) {
final Class<?>[] interfaces = targetClass.getInterfaces();
if (ArrayUtil.isNotEmpty(interfaces)) {
CollUtil.addAll(nextClasses, interfaces);
}
}
}
/**
* {@link #includeSuperClass}{@code true}nextClasses
*
* @param nextClassQueue
* @param targetClass
*/
protected void scanSuperClassIfNecessary(List<Class<?>> nextClassQueue, Class<?> targetClass) {
if (includeSuperClass) {
final Class<?> superClass = targetClass.getSuperclass();
if (!ObjectUtil.equals(superClass, Object.class) && ObjectUtil.isNotNull(superClass)) {
nextClassQueue.add(superClass);
}
}
}
/**
* 使
*
* @param target
* @return
*/
protected Class<?> convert(Class<?> target) {
if (hasConverters) {
for (final UnaryOperator<Class<?>> converter : converters) {
target = converter.apply(target);
}
}
return target;
}
/**
* jdk
*/
public static class JdkProxyClassConverter implements UnaryOperator<Class<?>> {
@Override
public Class<?> apply(Class<?> sourceClass) {
return Proxy.isProxyClass(sourceClass) ? apply(sourceClass.getSuperclass()) : sourceClass;
}
}
}

View File

@ -0,0 +1,198 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.annotation.AnnotationUtil;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* <p>
*
* <p>
* <ul>
* <li>{@link #NOTHING}</li>
* <li>{@link #DIRECTLY}{@link Inherited}</li>
* <li>
* {@link #DIRECTLY_AND_META_ANNOTATION}{@link Inherited}
*
* </li>
* <li>{@link #SUPERCLASS}</li>
* <li>{@link #SUPERCLASS_AND_META_ANNOTATION}</li>
* <li>{@link #INTERFACE}</li>
* <li>{@link #INTERFACE_AND_META_ANNOTATION}</li>
* <li>{@link #TYPE_HIERARCHY}</li>
* <li>{@link #TYPE_HIERARCHY_AND_META_ANNOTATION}</li>
* </ul>
*
* @author huangchengxing
* @see TypeAnnotationScanner
* @see MethodAnnotationScanner
* @see FieldAnnotationScanner
* @see MetaAnnotationScanner
* @see ElementAnnotationScanner
* @see GenericAnnotationScanner
*/
public interface AnnotationScanner {
// ============================ 预置的扫描器实例 ============================
/**
*
*/
AnnotationScanner NOTHING = new EmptyAnnotationScanner();
/**
* {@link Inherited}
*/
AnnotationScanner DIRECTLY = new GenericAnnotationScanner(false, false, false);
/**
* {@link Inherited}
*/
AnnotationScanner DIRECTLY_AND_META_ANNOTATION = new GenericAnnotationScanner(true, false, false);
/**
*
*/
AnnotationScanner SUPERCLASS = new GenericAnnotationScanner(false, true, false);
/**
*
*/
AnnotationScanner SUPERCLASS_AND_META_ANNOTATION = new GenericAnnotationScanner(true, true, false);
/**
*
*/
AnnotationScanner INTERFACE = new GenericAnnotationScanner(false, false, true);
/**
*
*/
AnnotationScanner INTERFACE_AND_META_ANNOTATION = new GenericAnnotationScanner(true, false, true);
/**
*
*/
AnnotationScanner TYPE_HIERARCHY = new GenericAnnotationScanner(false, true, true);
/**
*
*/
AnnotationScanner TYPE_HIERARCHY_AND_META_ANNOTATION = new GenericAnnotationScanner(true, true, true);
// ============================ 静态方法 ============================
/**
* 使
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param scanners
* @return
*/
static List<Annotation> scanByAnySupported(AnnotatedElement annotatedEle, AnnotationScanner... scanners) {
if (ObjectUtil.isNull(annotatedEle) && ArrayUtil.isNotEmpty(scanners)) {
return Collections.emptyList();
}
return Stream.of(scanners)
.filter(scanner -> scanner.support(annotatedEle))
.findFirst()
.map(scanner -> scanner.getAnnotations(annotatedEle))
.orElseGet(Collections::emptyList);
}
/**
*
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param scanners
* @return
*/
static List<Annotation> scanByAllSupported(AnnotatedElement annotatedEle, AnnotationScanner... scanners) {
if (ObjectUtil.isNull(annotatedEle) && ArrayUtil.isNotEmpty(scanners)) {
return Collections.emptyList();
}
return Stream.of(scanners)
.map(scanner -> scanner.getAnnotationsIfSupport(annotatedEle))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
// ============================ 抽象方法 ============================
/**
*
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
default boolean support(AnnotatedElement annotatedEle) {
return false;
}
/**
* {@link #support(AnnotatedElement)}true
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
default List<Annotation> getAnnotations(AnnotatedElement annotatedEle) {
final List<Annotation> annotations = new ArrayList<>();
scan((index, annotation) -> annotations.add(annotation), annotatedEle, null);
return annotations;
}
/**
* {@link #support(AnnotatedElement)}{@code true}
* {@link #getAnnotations(AnnotatedElement)}
* {@link Collections#emptyList()}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
default List<Annotation> getAnnotationsIfSupport(AnnotatedElement annotatedEle) {
return support(annotatedEle) ? getAnnotations(annotatedEle) : Collections.emptyList();
}
/**
*
* {@link #support(AnnotatedElement)}true
*
* @param consumer
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param filter
*/
default void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
filter = ObjectUtil.defaultIfNull(filter, (a)->annotation -> true);
for (final Annotation annotation : annotatedEle.getAnnotations()) {
if (AnnotationUtil.isNotJdkMateAnnotation(annotation.annotationType()) && filter.test(annotation)) {
consumer.accept(0, annotation);
}
}
}
/**
* {@link #support(AnnotatedElement)}{@code true}{@link #scan(BiConsumer, AnnotatedElement, Predicate)}
*
* @param consumer
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param filter
*/
default void scanIfSupport(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
if (support(annotatedEle)) {
scan(consumer, annotatedEle, filter);
}
}
}

View File

@ -0,0 +1,44 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* {@link AnnotatedElement}
*
* @author huangchengxing
*/
public class ElementAnnotationScanner implements AnnotationScanner {
/**
* {@code true}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
@Override
public boolean support(AnnotatedElement annotatedEle) {
return ObjectUtil.isNotNull(annotatedEle);
}
/**
* {@link AnnotatedElement}{@link #support(AnnotatedElement)}true
*
* @param consumer
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param filter
*/
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
filter = ObjectUtil.defaultIfNull(filter,a-> t -> true);
Stream.of(annotatedEle.getAnnotations())
.filter(filter)
.forEach(annotation -> consumer.accept(0, annotation));
}
}

View File

@ -0,0 +1,31 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
/**
*
*
* @author huangchengxing
*/
public class EmptyAnnotationScanner implements AnnotationScanner {
@Override
public boolean support(AnnotatedElement annotatedEle) {
return true;
}
@Override
public List<Annotation> getAnnotations(AnnotatedElement annotatedEle) {
return Collections.emptyList();
}
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
// do nothing
}
}

View File

@ -0,0 +1,47 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.annotation.AnnotationUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
/**
* {@link Field}
*
* @author huangchengxing
*/
public class FieldAnnotationScanner implements AnnotationScanner {
/**
* {@link Field}{@code true}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
@Override
public boolean support(AnnotatedElement annotatedEle) {
return annotatedEle instanceof Field;
}
/**
* {@link Field}{@link #support(AnnotatedElement)}true
*
* @param consumer
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param filter
*/
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
filter = ObjectUtil.defaultIfNull(filter, a -> annotation -> true);
for (final Annotation annotation : annotatedEle.getAnnotations()) {
if (AnnotationUtil.isNotJdkMateAnnotation(annotation.annotationType()) && filter.test(annotation)) {
consumer.accept(0, annotation);
}
}
}
}

View File

@ -0,0 +1,149 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.map.multi.ListValueMap;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
/**
* <p>{@link AnnotatedElement}
*
* <p>{@link AnnotatedElement}
* <ul>
* <li>
* {@link Method}
*
* </li>
* <li>
* {@link Class}
*
* </li>
* <li>{@link Method}{@link Class}</li>
* </ul>
*
*
* @author huangchengxing
* @see TypeAnnotationScanner
* @see MethodAnnotationScanner
* @see MetaAnnotationScanner
* @see ElementAnnotationScanner
*/
public class GenericAnnotationScanner implements AnnotationScanner {
/**
*
*/
private final AnnotationScanner typeScanner;
/**
*
*/
private final AnnotationScanner methodScanner;
/**
*
*/
private final AnnotationScanner metaScanner;
/**
*
*/
private final AnnotationScanner elementScanner;
/**
* {@link AnnotatedElement}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
@Override
public boolean support(AnnotatedElement annotatedEle) {
return true;
}
/**
*
*
* @param enableScanMetaAnnotation
* @param enableScanSupperClass
* @param enableScanSupperInterface
*/
public GenericAnnotationScanner(
boolean enableScanMetaAnnotation,
boolean enableScanSupperClass,
boolean enableScanSupperInterface) {
this.metaScanner = enableScanMetaAnnotation ? new MetaAnnotationScanner() : new EmptyAnnotationScanner();
this.typeScanner = new TypeAnnotationScanner(
enableScanSupperClass, enableScanSupperInterface, a -> true, Collections.emptySet()
);
this.methodScanner = new MethodAnnotationScanner(
enableScanSupperClass, enableScanSupperInterface, a -> true, Collections.emptySet()
);
this.elementScanner = new ElementAnnotationScanner();
}
/**
*
*
* @param consumer
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param filter
*/
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
filter = ObjectUtil.defaultIfNull(filter, a -> t -> true);
if (ObjectUtil.isNull(annotatedEle)) {
return;
}
// 注解元素是类
if (annotatedEle instanceof Class) {
scanElements(typeScanner, consumer, annotatedEle, filter);
}
// 注解元素是方法
else if (annotatedEle instanceof Method) {
scanElements(methodScanner, consumer, annotatedEle, filter);
}
// 注解元素是其他类型
else {
scanElements(elementScanner, consumer, annotatedEle, filter);
}
}
/**
*
*
* @param scanner 使
* @param consumer
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param filter
*/
private void scanElements(
AnnotationScanner scanner,
BiConsumer<Integer, Annotation> consumer,
AnnotatedElement annotatedEle,
Predicate<Annotation> filter) {
// 扫描类上注解
final ListValueMap<Integer, Annotation> classAnnotations = new ListValueMap<>(new LinkedHashMap<>());
scanner.scan((index, annotation) -> {
if (filter.test(annotation)) {
classAnnotations.putValue(index, annotation);
}
}, annotatedEle, filter);
// 扫描元注解
classAnnotations.forEach((index, annotations) ->
annotations.forEach(annotation -> {
consumer.accept(index, annotation);
metaScanner.scan(consumer, annotation.annotationType(), filter);
})
);
}
}

View File

@ -0,0 +1,110 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.annotation.AnnotationUtil;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.util.ClassUtil;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
*
* {@link TypeAnnotationScanner}
*
* @author huangchengxing
* @see TypeAnnotationScanner
*/
public class MetaAnnotationScanner implements AnnotationScanner {
/**
*
*/
private final boolean includeSupperMetaAnnotation;
/**
*
*
* @param includeSupperMetaAnnotation
*/
public MetaAnnotationScanner(boolean includeSupperMetaAnnotation) {
this.includeSupperMetaAnnotation = includeSupperMetaAnnotation;
}
/**
*
*/
public MetaAnnotationScanner() {
this(true);
}
/**
* {@link Annotation}{@link Class}{@code true}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
@Override
public boolean support(AnnotatedElement annotatedEle) {
return (annotatedEle instanceof Class && ClassUtil.isAssignable(Annotation.class, (Class<?>) annotatedEle));
}
/**
* {@link #support(AnnotatedElement)}true
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
@Override
public List<Annotation> getAnnotations(AnnotatedElement annotatedEle) {
final List<Annotation> annotations = new ArrayList<>();
scan(
(index, annotation) -> annotations.add(annotation), annotatedEle,
annotation -> ObjectUtil.notEqual(annotation, annotatedEle)
);
return annotations;
}
/**
* 广
*
* @param consumer
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @param filter
*/
@SuppressWarnings("unchecked")
@Override
public void scan(BiConsumer<Integer, Annotation> consumer, AnnotatedElement annotatedEle, Predicate<Annotation> filter) {
filter = ObjectUtil.defaultIfNull(filter, a -> t -> true);
Set<Class<? extends Annotation>> accessed = new HashSet<>();
final Deque<List<Class<? extends Annotation>>> deque = CollUtil.newLinkedList(CollUtil.newArrayList((Class<? extends Annotation>) annotatedEle));
int distance = 0;
do {
final List<Class<? extends Annotation>> annotationTypes = deque.removeFirst();
for (final Class<? extends Annotation> type : annotationTypes) {
final List<Annotation> metaAnnotations = Stream.of(type.getAnnotations())
.filter(a -> !AnnotationUtil.isJdkMetaAnnotation(a.annotationType()))
.filter(filter)
.collect(Collectors.toList());
for (final Annotation metaAnnotation : metaAnnotations) {
consumer.accept(distance, metaAnnotation);
}
accessed.add(type);
List<Class<? extends Annotation>> next = metaAnnotations.stream()
.map(Annotation::annotationType)
.filter(t -> !accessed.contains(t))
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(next)) {
deque.addLast(next);
}
}
distance++;
} while (includeSupperMetaAnnotation && !deque.isEmpty());
}
}

View File

@ -0,0 +1,133 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import aiyh.utils.tool.cn.hutool.core.util.ClassUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* {@link Method}
*
* @author huangchengxing
*/
public class MethodAnnotationScanner extends AbstractTypeAnnotationScanner<MethodAnnotationScanner> implements AnnotationScanner {
/**
*
*/
public MethodAnnotationScanner() {
this(false);
}
/**
*
*
* @param scanSameSignatureMethod
*/
public MethodAnnotationScanner(boolean scanSameSignatureMethod) {
this(scanSameSignatureMethod, targetClass -> true, CollUtil.newLinkedHashSet());
}
/**
*
*
* @param scanSameSignatureMethod
* @param filter
* @param excludeTypes
*/
public MethodAnnotationScanner(boolean scanSameSignatureMethod, Predicate<Class<?>> filter, Set<Class<?>> excludeTypes) {
super(scanSameSignatureMethod, scanSameSignatureMethod, filter, excludeTypes);
}
/**
*
*
* @param includeSuperClass
* @param includeInterfaces
* @param filter
* @param excludeTypes
*/
public MethodAnnotationScanner(boolean includeSuperClass, boolean includeInterfaces, Predicate<Class<?>> filter, Set<Class<?>> excludeTypes) {
super(includeSuperClass, includeInterfaces, filter, excludeTypes);
}
/**
* {@link Method}{@code true}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return boolean
*/
@Override
public boolean support(AnnotatedElement annotatedEle) {
return annotatedEle instanceof Method;
}
/**
*
*
* @param annotatedElement
* @return
* @see Method#getDeclaringClass()
*/
@Override
protected Class<?> getClassFormAnnotatedElement(AnnotatedElement annotatedElement) {
return ((Method)annotatedElement).getDeclaringClass();
}
/**
* /
*
* @param source
* @param index
* @param targetClass
* @return
*/
@Override
protected Annotation[] getAnnotationsFromTargetClass(AnnotatedElement source, int index, Class<?> targetClass) {
final Method sourceMethod = (Method) source;
return Stream.of(ClassUtil.getDeclaredMethods(targetClass))
.filter(superMethod -> !superMethod.isBridge())
.filter(superMethod -> hasSameSignature(sourceMethod, superMethod))
.map(AnnotatedElement::getAnnotations)
.flatMap(Stream::of)
.toArray(Annotation[]::new);
}
/**
*
*
* @param scanSuperMethodIfOverride
* @return
*/
public MethodAnnotationScanner setScanSameSignatureMethod(boolean scanSuperMethodIfOverride) {
setIncludeInterfaces(scanSuperMethodIfOverride);
setIncludeSuperClass(scanSuperMethodIfOverride);
return this;
}
/**
*
*/
private boolean hasSameSignature(Method sourceMethod, Method superMethod) {
if (false == StrUtil.equals(sourceMethod.getName(), superMethod.getName())) {
return false;
}
final Class<?>[] sourceParameterTypes = sourceMethod.getParameterTypes();
final Class<?>[] targetParameterTypes = superMethod.getParameterTypes();
if (sourceParameterTypes.length != targetParameterTypes.length) {
return false;
}
if (!ArrayUtil.containsAll(sourceParameterTypes, targetParameterTypes)) {
return false;
}
return ClassUtil.isAssignable(superMethod.getReturnType(), sourceMethod.getReturnType());
}
}

View File

@ -0,0 +1,105 @@
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Proxy;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/**
* {@link Class}
*
* @author huangchengxing
*/
public class TypeAnnotationScanner extends AbstractTypeAnnotationScanner<TypeAnnotationScanner> implements AnnotationScanner {
/**
*
*
* @param includeSupperClass
* @param includeInterfaces
* @param filter
* @param excludeTypes
*/
public TypeAnnotationScanner(boolean includeSupperClass, boolean includeInterfaces, Predicate<Class<?>> filter, Set<Class<?>> excludeTypes) {
super(includeSupperClass, includeInterfaces, filter, excludeTypes);
}
/**
*
*/
public TypeAnnotationScanner() {
this(true, true, t -> true, CollUtil.newLinkedHashSet());
}
/**
* {@link Class}{@code true}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
@Override
public boolean support(AnnotatedElement annotatedEle) {
return annotatedEle instanceof Class;
}
/**
* {@link Class}
*
* @param annotatedEle {@link AnnotatedElement}ClassMethodFieldConstructorReflectPermission
* @return
*/
@Override
protected Class<?> getClassFormAnnotatedElement(AnnotatedElement annotatedEle) {
return (Class<?>)annotatedEle;
}
/**
* {@link Class#getAnnotations()}
*
* @param source
* @param index
* @param targetClass
* @return
*/
@Override
protected Annotation[] getAnnotationsFromTargetClass(AnnotatedElement source, int index, Class<?> targetClass) {
return targetClass.getAnnotations();
}
/**
*
*
* @param includeSuperClass
* @return
*/
@Override
public TypeAnnotationScanner setIncludeSuperClass(boolean includeSuperClass) {
return super.setIncludeSuperClass(includeSuperClass);
}
/**
*
*
* @param includeInterfaces
* @return
*/
@Override
public TypeAnnotationScanner setIncludeInterfaces(boolean includeInterfaces) {
return super.setIncludeInterfaces(includeInterfaces);
}
/**
* jdk
*/
public static class JdkProxyClassConverter implements UnaryOperator<Class<?>> {
@Override
public Class<?> apply(Class<?> sourceClass) {
return Proxy.isProxyClass(sourceClass) ? apply(sourceClass.getSuperclass()) : sourceClass;
}
}
}

View File

@ -0,0 +1,7 @@
/**
*
*
* @author looly
*
*/
package aiyh.utils.tool.cn.hutool.core.annotation.scanner;

View File

@ -0,0 +1,324 @@
package aiyh.utils.tool.cn.hutool.core.bean;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.map.CaseInsensitiveMap;
import aiyh.utils.tool.cn.hutool.core.util.BooleanUtil;
import aiyh.utils.tool.cn.hutool.core.util.ModifierUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* BeanBeanInfoJavaBeansettersgetters<br>
* GetterSetter
*
* <pre>
* 1.
* 2. GettergetXXXisXXXgetIsXXX
* 3. SettersetXXXsetIsXXX
* 4. Setter
* </pre>
*
* @author looly
* @since 3.1.2
*/
public class BeanDesc implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Bean
*/
private final Class<?> beanClass;
/**
* Map
*/
private final Map<String, PropDesc> propMap = new LinkedHashMap<>();
/**
*
*
* @param beanClass Bean
*/
public BeanDesc(Class<?> beanClass) {
Assert.notNull(beanClass);
this.beanClass = beanClass;
init();
}
/**
* Bean
*
* @return Bean
*/
public String getName() {
return this.beanClass.getName();
}
/**
* Bean
*
* @return Bean
*/
public String getSimpleName() {
return this.beanClass.getSimpleName();
}
/**
* -Map
*
* @param ignoreCase truefalse
* @return -Map
*/
public Map<String, PropDesc> getPropMap(boolean ignoreCase) {
return ignoreCase ? new CaseInsensitiveMap<>(1, this.propMap) : this.propMap;
}
/**
*
*
* @return {@link PropDesc}
*/
public Collection<PropDesc> getProps() {
return this.propMap.values();
}
/**
* null
*
* @param fieldName
* @return {@link PropDesc}
*/
public PropDesc getProp(String fieldName) {
return this.propMap.get(fieldName);
}
/**
* null
*
* @param fieldName
* @return
*/
public Field getField(String fieldName) {
final PropDesc desc = this.propMap.get(fieldName);
return null == desc ? null : desc.getField();
}
/**
* Getternull
*
* @param fieldName
* @return Getter
*/
public Method getGetter(String fieldName) {
final PropDesc desc = this.propMap.get(fieldName);
return null == desc ? null : desc.getGetter();
}
/**
* Setternull
*
* @param fieldName
* @return Setter
*/
public Method getSetter(String fieldName) {
final PropDesc desc = this.propMap.get(fieldName);
return null == desc ? null : desc.getSetter();
}
// ------------------------------------------------------------------------------------------------------ Private method start
/**
* <br>
* GetterSettergetXXXsetXXX
*
* @return this
*/
private BeanDesc init() {
final Method[] gettersAndSetters = ReflectUtil.getMethods(this.beanClass, ReflectUtil::isGetterOrSetterIgnoreCase);
PropDesc prop;
for (Field field : ReflectUtil.getFields(this.beanClass)) {
// 排除静态属性和对象子类
if (false == ModifierUtil.isStatic(field) && false == ReflectUtil.isOuterClassField(field)) {
prop = createProp(field, gettersAndSetters);
// 只有不存在时才放入,防止父类属性覆盖子类属性
this.propMap.putIfAbsent(prop.getFieldName(), prop);
}
}
return this;
}
/**
* <br>
* GetterSetter
*
* <pre>
* 1.
* 2. GettergetXXXisXXXgetIsXXX
* 3. SettersetXXXsetIsXXX
* 4. Setter
* </pre>
*
* @param field
* @param methods
* @return {@link PropDesc}
* @since 4.0.2
*/
private PropDesc createProp(Field field, Method[] methods) {
final PropDesc prop = findProp(field, methods, false);
// 忽略大小写重新匹配一次
if (null == prop.getter || null == prop.setter) {
final PropDesc propIgnoreCase = findProp(field, methods, true);
if (null == prop.getter) {
prop.getter = propIgnoreCase.getter;
}
if (null == prop.setter) {
prop.setter = propIgnoreCase.setter;
}
}
return prop;
}
/**
* GetterSetter
*
* @param field
* @param gettersOrSetters GetterSetter
* @param ignoreCase
* @return PropDesc
*/
private PropDesc findProp(Field field, Method[] gettersOrSetters, boolean ignoreCase) {
final String fieldName = field.getName();
final Class<?> fieldType = field.getType();
final boolean isBooleanField = BooleanUtil.isBoolean(fieldType);
Method getter = null;
Method setter = null;
String methodName;
for (Method method : gettersOrSetters) {
methodName = method.getName();
if (method.getParameterCount() == 0) {
// 无参数可能为Getter方法
if (isMatchGetter(methodName, fieldName, isBooleanField, ignoreCase)) {
// 方法名与字段名匹配则为Getter方法
getter = method;
}
} else if (isMatchSetter(methodName, fieldName, isBooleanField, ignoreCase)) {
// setter方法的参数类型和字段类型必须一致或参数类型是字段类型的子类
if(fieldType.isAssignableFrom(method.getParameterTypes()[0])){
setter = method;
}
}
if (null != getter && null != setter) {
// 如果Getter和Setter方法都找到了不再继续寻找
break;
}
}
return new PropDesc(field, getter, setter);
}
/**
* Getter<br>
*
*
* <pre>
* -
* isName - isName
* isName - isIsName
* isName - getIsName
* name - isName
* name - getName
* </pre>
*
* @param methodName
* @param fieldName
* @param isBooleanField Boolean
* @param ignoreCase
* @return
*/
private boolean isMatchGetter(String methodName, String fieldName, boolean isBooleanField, boolean ignoreCase) {
final String handledFieldName;
if (ignoreCase) {
// 全部转为小写,忽略大小写比较
methodName = methodName.toLowerCase();
handledFieldName = fieldName.toLowerCase();
fieldName = handledFieldName;
} else {
handledFieldName = StrUtil.upperFirst(fieldName);
}
// 针对Boolean类型特殊检查
if (isBooleanField) {
if (fieldName.startsWith("is")) {
// 字段已经是is开头
if (methodName.equals(fieldName) // isName -》 isName
|| ("get" + handledFieldName).equals(methodName)// isName -》 getIsName
|| ("is" + handledFieldName).equals(methodName)// isName -》 isIsName
) {
return true;
}
} else if (("is" + handledFieldName).equals(methodName)) {
// 字段非is开头 name -》 isName
return true;
}
}
// 包括boolean的任何类型只有一种匹配情况name -》 getName
return ("get" + handledFieldName).equals(methodName);
}
/**
* Setter<br>
*
*
* <pre>
* -
* isName - setName
* isName - setIsName
* name - setName
* </pre>
*
* @param methodName
* @param fieldName
* @param isBooleanField Boolean
* @param ignoreCase
* @return
*/
private boolean isMatchSetter(String methodName, String fieldName, boolean isBooleanField, boolean ignoreCase) {
final String handledFieldName;
if (ignoreCase) {
// 全部转为小写,忽略大小写比较
methodName = methodName.toLowerCase();
handledFieldName = fieldName.toLowerCase();
fieldName = handledFieldName;
} else {
handledFieldName = StrUtil.upperFirst(fieldName);
}
// 非标准Setter方法跳过
if (false == methodName.startsWith("set")) {
return false;
}
// 针对Boolean类型特殊检查
if (isBooleanField && fieldName.startsWith("is")) {
// 字段是is开头
if (("set" + StrUtil.removePrefix(fieldName, "is")).equals(methodName)// isName -》 setName
|| ("set" + handledFieldName).equals(methodName)// isName -》 setIsName
) {
return true;
}
}
// 包括boolean的任何类型只有一种匹配情况name -》 setName
return ("set" + handledFieldName).equals(methodName);
}
// ------------------------------------------------------------------------------------------------------ Private method end
}

View File

@ -0,0 +1,37 @@
package aiyh.utils.tool.cn.hutool.core.bean;
import aiyh.utils.tool.cn.hutool.core.lang.func.Func0;
import aiyh.utils.tool.cn.hutool.core.map.WeakConcurrentMap;
/**
* Bean<br>
*
*
* @author Looly
*/
public enum BeanDescCache {
INSTANCE;
private final WeakConcurrentMap<Class<?>, BeanDesc> bdCache = new WeakConcurrentMap<>();
/**
* {@link BeanDesc}Map
*
* @param beanClass Bean
* @param supplier
* @return {@link BeanDesc}
* @since 5.4.2
*/
public BeanDesc getBeanDesc(Class<?> beanClass, Func0<BeanDesc> supplier) {
return bdCache.computeIfAbsent(beanClass, (key)->supplier.callWithRuntimeException());
}
/**
* Bean
*
* @since 5.7.21
*/
public void clear() {
this.bdCache.clear();
}
}

View File

@ -0,0 +1,32 @@
package aiyh.utils.tool.cn.hutool.core.bean;
import aiyh.utils.tool.cn.hutool.core.exceptions.ExceptionUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
/**
* Bean
* @author xiaoleilu
*/
public class BeanException extends RuntimeException{
private static final long serialVersionUID = -8096998667745023423L;
public BeanException(Throwable e) {
super(ExceptionUtil.getMessage(e), e);
}
public BeanException(String message) {
super(message);
}
public BeanException(String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params));
}
public BeanException(String message, Throwable throwable) {
super(message, throwable);
}
public BeanException(Throwable throwable, String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params), throwable);
}
}

View File

@ -0,0 +1,80 @@
package aiyh.utils.tool.cn.hutool.core.bean;
import aiyh.utils.tool.cn.hutool.core.lang.func.Func0;
import aiyh.utils.tool.cn.hutool.core.map.ReferenceConcurrentMap;
import aiyh.utils.tool.cn.hutool.core.map.WeakConcurrentMap;
import java.beans.PropertyDescriptor;
import java.util.Map;
/**
* Bean<br>
*
*
* @author Looly
*/
public enum BeanInfoCache {
INSTANCE;
private final WeakConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> pdCache = new WeakConcurrentMap<>();
private final WeakConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> ignoreCasePdCache = new WeakConcurrentMap<>();
/**
* {@link PropertyDescriptor}Map
*
* @param beanClass Bean
* @param ignoreCase
* @return {@link PropertyDescriptor}Map
*/
public Map<String, PropertyDescriptor> getPropertyDescriptorMap(Class<?> beanClass, boolean ignoreCase) {
return getCache(ignoreCase).get(beanClass);
}
/**
* {@link PropertyDescriptor}Map
*
* @param beanClass Bean
* @param ignoreCase
* @param supplier
* @return {@link PropertyDescriptor}Map
* @since 5.4.1
*/
public Map<String, PropertyDescriptor> getPropertyDescriptorMap(
Class<?> beanClass,
boolean ignoreCase,
Func0<Map<String, PropertyDescriptor>> supplier) {
return getCache(ignoreCase).computeIfAbsent(beanClass, (key)->supplier.callWithRuntimeException());
}
/**
*
*
* @param beanClass Bean
* @param fieldNamePropertyDescriptorMap {@link PropertyDescriptor}Map
* @param ignoreCase
*/
public void putPropertyDescriptorMap(Class<?> beanClass, Map<String, PropertyDescriptor> fieldNamePropertyDescriptorMap, boolean ignoreCase) {
getCache(ignoreCase).put(beanClass, fieldNamePropertyDescriptorMap);
}
/**
*
*
* @since 5.7.21
*/
public void clear() {
this.pdCache.clear();
this.ignoreCasePdCache.clear();
}
/**
* Cache
*
* @param ignoreCase
* @return {@link ReferenceConcurrentMap}
* @since 5.4.1
*/
private ReferenceConcurrentMap<Class<?>, Map<String, PropertyDescriptor>> getCache(boolean ignoreCase) {
return ignoreCase ? ignoreCasePdCache : pdCache;
}
}

View File

@ -0,0 +1,324 @@
package aiyh.utils.tool.cn.hutool.core.bean;
import aiyh.utils.tool.cn.hutool.core.collection.CollUtil;
import aiyh.utils.tool.cn.hutool.core.collection.ListUtil;
import aiyh.utils.tool.cn.hutool.core.convert.Convert;
import aiyh.utils.tool.cn.hutool.core.map.MapUtil;
import aiyh.utils.tool.cn.hutool.core.util.ArrayUtil;
import aiyh.utils.tool.cn.hutool.core.util.CharUtil;
import aiyh.utils.tool.cn.hutool.core.util.NumberUtil;
import aiyh.utils.tool.cn.hutool.core.util.StrUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* BeanBeanBean<br>
* Bean
* <ol>
* <li>.BeanMapkey</li>
* <li>[]index</li>
* </ol>
* <p>
*
*
* <pre>
* persion
* persion.name
* persons[3]
* person.friends[5].name
* ['person']['friends'][5]['name']
* </pre>
*
* @author Looly
* @since 4.0.6
*/
public class BeanPath implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
private static final char[] EXP_CHARS = {CharUtil.DOT, CharUtil.BRACKET_START, CharUtil.BRACKET_END};
private boolean isStartWith = false;
protected List<String> patternParts;
/**
* BeanBean<br>
* BeanBeanBean<br>
* Bean
* <ol>
* <li>.BeanMapkey</li>
* <li>[]index</li>
* </ol>
* <p>
*
*
* <pre>
* persion
* persion.name
* persons[3]
* person.friends[5].name
* ['person']['friends'][5]['name']
* </pre>
*
* @param expression
* @return BeanPath
*/
public static BeanPath create(final String expression) {
return new BeanPath(expression);
}
/**
*
*
* @param expression
*/
public BeanPath(final String expression) {
init(expression);
}
/**
*
*
* @return
*/
public List<String> getPatternParts() {
return this.patternParts;
}
/**
* Bean
*
* @param bean BeanMapList
* @return null
*/
public Object get(final Object bean) {
return get(this.patternParts, bean, false);
}
/**
* filed<br>
* ListMapputkeyBean<br>
*
*
* <pre>
* 1. ListList
* 2.
* </pre>
*
* @param bean BeanMapList
* @param value
*/
public void set(final Object bean, final Object value) {
set(bean, this.patternParts, lastIsNumber(this.patternParts), value);
}
@Override
public String toString() {
return this.patternParts.toString();
}
//region Private Methods
/**
* filed<br>
* ListMapputkeyBean<br>
*
*
* <pre>
* 1. ListList
* 2.
* </pre>
*
* @param bean BeanMapList
* @param patternParts
* @param value
* @return
*/
private void set(Object bean, List<String> patternParts, boolean nextNumberPart, Object value) {
Object subBean = this.get(patternParts, bean, true);
if (null == subBean) {
final List<String> parentParts = getParentParts(patternParts);
this.set(bean, parentParts, lastIsNumber(parentParts), nextNumberPart ? new ArrayList<>() : new HashMap<>());
//set中有可能做过转换因此此处重新获取bean
subBean = this.get(patternParts, bean, true);
}
BeanUtil.setFieldValue(subBean, patternParts.get(patternParts.size() - 1), value);
}
/**
* path
*
* @param patternParts path
* @return
*/
private static boolean lastIsNumber(List<String> patternParts) {
return NumberUtil.isInteger(patternParts.get(patternParts.size() - 1));
}
/**
*
*
* @param patternParts
* @return
*/
private static List<String> getParentParts(List<String> patternParts) {
return patternParts.subList(0, patternParts.size() - 1);
}
/**
* Bean
*
* @param patternParts
* @param bean BeanMapList
* @param ignoreLast setread
* @return null
*/
private Object get(final List<String> patternParts, final Object bean, final boolean ignoreLast) {
int length = patternParts.size();
if (ignoreLast) {
length--;
}
Object subBean = bean;
boolean isFirst = true;
String patternPart;
for (int i = 0; i < length; i++) {
patternPart = patternParts.get(i);
subBean = getFieldValue(subBean, patternPart);
if (null == subBean) {
// 支持表达式的第一个对象为Bean本身若用户定义表达式$开头,则不做此操作)
if (isFirst && false == this.isStartWith && BeanUtil.isMatchName(bean, patternPart, true)) {
subBean = bean;
isFirst = false;
} else {
return null;
}
}
}
return subBean;
}
@SuppressWarnings("unchecked")
private static Object getFieldValue(final Object bean, final String expression) {
if (StrUtil.isBlank(expression)) {
return null;
}
if (StrUtil.contains(expression, ':')) {
// [start:end:step] 模式
final List<String> parts = StrUtil.splitTrim(expression, ':');
final int start = Integer.parseInt(parts.get(0));
final int end = Integer.parseInt(parts.get(1));
int step = 1;
if (3 == parts.size()) {
step = Integer.parseInt(parts.get(2));
}
if (bean instanceof Collection) {
return CollUtil.sub((Collection<?>) bean, start, end, step);
} else if (ArrayUtil.isArray(bean)) {
return ArrayUtil.sub(bean, start, end, step);
}
} else if (StrUtil.contains(expression, ',')) {
// [num0,num1,num2...]模式或者['key0','key1']模式
final List<String> keys = StrUtil.splitTrim(expression, ',');
if (bean instanceof Collection) {
return CollUtil.getAny((Collection<?>) bean, Convert.convert(int[].class, keys));
} else if (ArrayUtil.isArray(bean)) {
return ArrayUtil.getAny(bean, Convert.convert(int[].class, keys));
} else {
final String[] unWrappedKeys = new String[keys.size()];
for (int i = 0; i < unWrappedKeys.length; i++) {
unWrappedKeys[i] = StrUtil.unWrap(keys.get(i), '\'');
}
if (bean instanceof Map) {
// 只支持String为key的Map
return MapUtil.getAny((Map<String, ?>) bean, unWrappedKeys);
} else {
final Map<String, Object> map = BeanUtil.beanToMap(bean);
return MapUtil.getAny(map, unWrappedKeys);
}
}
} else {
// 数字或普通字符串
return BeanUtil.getFieldValue(bean, expression);
}
return null;
}
/**
*
*
* @param expression
*/
private void init(final String expression) {
final List<String> localPatternParts = new ArrayList<>();
final int length = expression.length();
final StringBuilder builder = new StringBuilder();
char c;
boolean isNumStart = false;// 下标标识符开始
boolean isInWrap = false; //标识是否在引号内
for (int i = 0; i < length; i++) {
c = expression.charAt(i);
if (0 == i && '$' == c) {
// 忽略开头的$符,表示当前对象
isStartWith = true;
continue;
}
if ('\'' == c) {
// 结束
isInWrap = (false == isInWrap);
continue;
}
if (false == isInWrap && ArrayUtil.contains(EXP_CHARS, c)) {
// 处理边界符号
if (CharUtil.BRACKET_END == c) {
// 中括号(数字下标)结束
if (false == isNumStart) {
throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find ']' but no '[' !", expression, i));
}
isNumStart = false;
// 中括号结束加入下标
} else {
if (isNumStart) {
// 非结束中括号情况下发现起始中括号报错(中括号未关闭)
throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find '[' but no ']' !", expression, i));
} else if (CharUtil.BRACKET_START == c) {
// 数字下标开始
isNumStart = true;
}
// 每一个边界符之前的表达式是一个完整的KEY开始处理KEY
}
if (builder.length() > 0) {
localPatternParts.add(builder.toString());
}
builder.setLength(0);
} else {
// 非边界符号,追加字符
builder.append(c);
}
}
// 末尾边界符检查
if (isNumStart) {
throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find '[' but no ']' !", expression, length - 1));
} else {
if (builder.length() > 0) {
localPatternParts.add(builder.toString());
}
}
// 不可变List
this.patternParts = ListUtil.unmodifiable(localPatternParts);
}
//endregion
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
package aiyh.utils.tool.cn.hutool.core.bean;
import aiyh.utils.tool.cn.hutool.core.clone.CloneSupport;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.util.ClassUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import java.io.Serializable;
import java.util.Map;
/**
* BeanBean<br>
* MapBean
*
* @author Looly
* @since 3.0.7
*/
public class DynaBean extends CloneSupport<DynaBean> implements Serializable {
private static final long serialVersionUID = 1L;
private final Class<?> beanClass;
private final Object bean;
/**
* DynaBean
*
* @param bean Bean
* @return DynaBean
*/
public static DynaBean create(Object bean) {
return new DynaBean(bean);
}
/**
* DynaBean
*
* @param beanClass Bean
* @return DynaBean
*/
public static DynaBean create(Class<?> beanClass) {
return new DynaBean(beanClass);
}
/**
* DynaBean
*
* @param beanClass Bean
* @param params Bean
* @return DynaBean
*/
public static DynaBean create(Class<?> beanClass, Object... params) {
return new DynaBean(beanClass, params);
}
//------------------------------------------------------------------------ Constructor start
/**
*
*
* @param beanClass Bean
* @param params Bean
*/
public DynaBean(Class<?> beanClass, Object... params) {
this(ReflectUtil.newInstance(beanClass, params));
}
/**
*
*
* @param beanClass Bean
*/
public DynaBean(Class<?> beanClass) {
this(ReflectUtil.newInstance(beanClass));
}
/**
*
*
* @param bean Bean
*/
public DynaBean(Object bean) {
Assert.notNull(bean);
if (bean instanceof DynaBean) {
bean = ((DynaBean) bean).getBean();
}
this.bean = bean;
this.beanClass = ClassUtil.getClass(bean);
}
//------------------------------------------------------------------------ Constructor end
/**
*
*
* @param <T>
* @param fieldName
* @return
* @throws BeanException
*/
@SuppressWarnings("unchecked")
public <T> T get(String fieldName) throws BeanException {
if (Map.class.isAssignableFrom(beanClass)) {
return (T) ((Map<?, ?>) bean).get(fieldName);
} else {
final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
if (null == prop) {
throw new BeanException("No public field or get method for {}", fieldName);
}
return (T) prop.getValue(bean);
}
}
/**
* bean
*
* @param fieldName
* @return bean
* @since 5.4.2
*/
public boolean containsProp(String fieldName) {
if (Map.class.isAssignableFrom(beanClass)) {
return ((Map<?, ?>) bean).containsKey(fieldName);
} else{
return null != BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
}
}
/**
* {@code null}
*
* @param <T>
* @param fieldName
* @return
* @since 3.1.1
*/
public <T> T safeGet(String fieldName) {
try {
return get(fieldName);
} catch (Exception e) {
return null;
}
}
/**
*
*
* @param fieldName
* @param value
* @throws BeanException
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public void set(String fieldName, Object value) throws BeanException {
if (Map.class.isAssignableFrom(beanClass)) {
((Map) bean).put(fieldName, value);
} else {
final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
if (null == prop) {
throw new BeanException("No public field or set method for {}", fieldName);
}
prop.setValue(bean, value);
}
}
/**
* Bean
*
* @param methodName
* @param params
* @return null
*/
public Object invoke(String methodName, Object... params) {
return ReflectUtil.invoke(this.bean, methodName, params);
}
/**
* Bean
*
* @param <T> Bean
* @return bean
*/
@SuppressWarnings("unchecked")
public <T> T getBean() {
return (T) this.bean;
}
/**
* Bean
*
* @param <T> Bean
* @return Bean
*/
@SuppressWarnings("unchecked")
public <T> Class<T> getBeanClass() {
return (Class<T>) this.beanClass;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bean == null) ? 0 : bean.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DynaBean other = (DynaBean) obj;
if (bean == null) {
return other.bean == null;
} else return bean.equals(other.bean);
}
@Override
public String toString() {
return this.bean.toString();
}
}

View File

@ -0,0 +1,29 @@
package aiyh.utils.tool.cn.hutool.core.bean;
/**
* ,null,
*
* @param <T> Null
* @author Lillls
* @since 5.5.0
*/
public class NullWrapperBean<T> {
private final Class<T> clazz;
/**
* @param clazz null
*/
public NullWrapperBean(Class<T> clazz) {
this.clazz = clazz;
}
/**
* null
*
* @return
*/
public Class<T> getWrappedClass() {
return clazz;
}
}

View File

@ -0,0 +1,404 @@
package aiyh.utils.tool.cn.hutool.core.bean;
import aiyh.utils.tool.cn.hutool.core.annotation.AnnotationUtil;
import aiyh.utils.tool.cn.hutool.core.annotation.PropIgnore;
import aiyh.utils.tool.cn.hutool.core.convert.Convert;
import aiyh.utils.tool.cn.hutool.core.util.ClassUtil;
import aiyh.utils.tool.cn.hutool.core.util.ModifierUtil;
import aiyh.utils.tool.cn.hutool.core.util.ReflectUtil;
import aiyh.utils.tool.cn.hutool.core.util.TypeUtil;
import java.beans.Transient;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/**
* gettersetter
*
* @author looly
*/
public class PropDesc {
/**
*
*/
final Field field;
/**
* Getter
*/
protected Method getter;
/**
* Setter
*/
protected Method setter;
/**
* <br>
* GetterSetter访
*
* @param field
* @param getter get
* @param setter set
*/
public PropDesc(Field field, Method getter, Method setter) {
this.field = field;
this.getter = ClassUtil.setAccessible(getter);
this.setter = ClassUtil.setAccessible(setter);
}
/**
* Alias
*
* @return
*/
public String getFieldName() {
return ReflectUtil.getFieldName(this.field);
}
/**
*
*
* @return
* @since 5.1.6
*/
public String getRawFieldName() {
return null == this.field ? null : this.field.getName();
}
/**
*
*
* @return
*/
public Field getField() {
return this.field;
}
/**
* <br>
* GetterSetter
*
* @return
*/
public Type getFieldType() {
if (null != this.field) {
return TypeUtil.getType(this.field);
}
return findPropType(getter, setter);
}
/**
* <br>
* GetterSetter
*
* @return
*/
public Class<?> getFieldClass() {
if (null != this.field) {
return TypeUtil.getClass(this.field);
}
return findPropClass(getter, setter);
}
/**
* Getter{@code null}
*
* @return Getter
*/
public Method getGetter() {
return this.getter;
}
/**
* Setter{@code null}
*
* @return {@link Method}Setter
*/
public Method getSetter() {
return this.setter;
}
/**
* {@link #getValue(Object)}
*
* @param checkTransient Transient
* @return
* @since 5.4.2
*/
public boolean isReadable(boolean checkTransient) {
// 检查是否有getter方法或是否为public修饰
if (null == this.getter && false == ModifierUtil.isPublic(this.field)) {
return false;
}
// 检查transient关键字和@Transient注解
if (checkTransient && isTransientForGet()) {
return false;
}
// 检查@PropIgnore注解
return false == isIgnoreGet();
}
/**
* <br>
* GetterGetterpublic<br>
* 使 {@link #isReadable(boolean)}
*
* @param bean Bean
* @return
* @since 4.0.5
*/
public Object getValue(Object bean) {
if (null != this.getter) {
return ReflectUtil.invoke(bean, this.getter);
} else if (ModifierUtil.isPublic(this.field)) {
return ReflectUtil.getFieldValue(bean, this.field);
}
return null;
}
/**
* <br>
* GetterGetterpublic
*
* @param bean Bean
* @param targetType null
* @param ignoreError
* @return this
* @since 5.4.2
*/
public Object getValue(Object bean, Type targetType, boolean ignoreError) {
Object result = null;
try {
result = getValue(bean);
} catch (Exception e) {
if (false == ignoreError) {
throw new BeanException(e, "Get value of [{}] error!", getFieldName());
}
}
if (null != result && null != targetType) {
// 尝试将结果转换为目标类型如果转换失败返回null即跳过此属性值。
// 来自issues#I41WKP@Gitee当忽略错误情况下目标类型转换失败应返回null
// 如果返回原值,在集合注入时会成功,但是集合取值时会报类型转换错误
return Convert.convertWithCheck(targetType, result, null, ignoreError);
}
return result;
}
/**
* {@link #getValue(Object)}
*
* @param checkTransient Transient
* @return
* @since 5.4.2
*/
public boolean isWritable(boolean checkTransient) {
// 检查是否有getter方法或是否为public修饰
if (null == this.setter && false == ModifierUtil.isPublic(this.field)) {
return false;
}
// 检查transient关键字和@Transient注解
if (checkTransient && isTransientForSet()) {
return false;
}
// 检查@PropIgnore注解
return false == isIgnoreSet();
}
/**
* Bean<br>
* SetterSetterpublic<br>
* 使 {@link #isWritable(boolean)}
*
* @param bean Bean
* @param value
* @return this
* @since 4.0.5
*/
public PropDesc setValue(Object bean, Object value) {
if (null != this.setter) {
ReflectUtil.invoke(bean, this.setter, value);
} else if (ModifierUtil.isPublic(this.field)) {
ReflectUtil.setFieldValue(bean, this.field, value);
}
return this;
}
/**
*
*
* @param bean Bean
* @param value
* @param ignoreNull {@code null}true
* @param ignoreError
* @return this
* @since 5.4.2
*/
public PropDesc setValue(Object bean, Object value, boolean ignoreNull, boolean ignoreError) {
return setValue(bean, value, ignoreNull, ignoreError, true);
}
/**
*
*
* @param bean Bean
* @param value
* @param ignoreNull {@code null}true
* @param ignoreError
* @param override bean{@code null}
* @return this
* @since 5.7.17
*/
public PropDesc setValue(Object bean, Object value, boolean ignoreNull, boolean ignoreError, boolean override) {
if (null == value && ignoreNull) {
return this;
}
// issue#I4JQ1N@Gitee
// 非覆盖模式下,如果目标值存在,则跳过
if (false == override && null != getValue(bean)) {
return this;
}
// 当类型不匹配的时候,执行默认转换
if (null != value) {
final Class<?> propClass = getFieldClass();
if (false == propClass.isInstance(value)) {
value = Convert.convertWithCheck(propClass, value, null, ignoreError);
}
}
// 属性赋值
if (null != value || false == ignoreNull) {
try {
this.setValue(bean, value);
} catch (Exception e) {
if (false == ignoreError) {
throw new BeanException(e, "Set value of [{}] error!", getFieldName());
}
// 忽略注入失败
}
}
return this;
}
//------------------------------------------------------------------------------------ Private method start
/**
* GetterSetter
*
* @param getter Getter
* @param setter Setter
* @return {@link Type}
*/
private Type findPropType(Method getter, Method setter) {
Type type = null;
if (null != getter) {
type = TypeUtil.getReturnType(getter);
}
if (null == type && null != setter) {
type = TypeUtil.getParamType(setter, 0);
}
return type;
}
/**
* GetterSetter
*
* @param getter Getter
* @param setter Setter
* @return {@link Type}
*/
private Class<?> findPropClass(Method getter, Method setter) {
Class<?> type = null;
if (null != getter) {
type = TypeUtil.getReturnClass(getter);
}
if (null == type && null != setter) {
type = TypeUtil.getFirstParamClass(setter);
}
return type;
}
/**
* {@link PropIgnore}
* <pre>
* 1. {@link PropIgnore}
* 2. setXXX{@link PropIgnore}
* </pre>
*
* @return
* @since 5.4.2
*/
private boolean isIgnoreSet() {
return AnnotationUtil.hasAnnotation(this.field, PropIgnore.class)
|| AnnotationUtil.hasAnnotation(this.setter, PropIgnore.class);
}
/**
* {@link PropIgnore}
* <pre>
* 1. {@link PropIgnore}
* 2. getXXX{@link PropIgnore}
* </pre>
*
* @return
* @since 5.4.2
*/
private boolean isIgnoreGet() {
return AnnotationUtil.hasAnnotation(this.field, PropIgnore.class)
|| AnnotationUtil.hasAnnotation(this.getter, PropIgnore.class);
}
/**
* GetterTransient
*
* @return Transient
* @since 5.3.11
*/
private boolean isTransientForGet() {
boolean isTransient = ModifierUtil.hasModifier(this.field, ModifierUtil.ModifierType.TRANSIENT);
// 检查Getter方法
if (false == isTransient && null != this.getter) {
isTransient = ModifierUtil.hasModifier(this.getter, ModifierUtil.ModifierType.TRANSIENT);
// 检查注解
if (false == isTransient) {
isTransient = AnnotationUtil.hasAnnotation(this.getter, Transient.class);
}
}
return isTransient;
}
/**
* GetterTransient
*
* @return Transient
* @since 5.3.11
*/
private boolean isTransientForSet() {
boolean isTransient = ModifierUtil.hasModifier(this.field, ModifierUtil.ModifierType.TRANSIENT);
// 检查Getter方法
if (false == isTransient && null != this.setter) {
isTransient = ModifierUtil.hasModifier(this.setter, ModifierUtil.ModifierType.TRANSIENT);
// 检查注解
if (false == isTransient) {
isTransient = AnnotationUtil.hasAnnotation(this.setter, Transient.class);
}
}
return isTransient;
}
//------------------------------------------------------------------------------------ Private method end
}

View File

@ -0,0 +1,28 @@
package aiyh.utils.tool.cn.hutool.core.bean.copier;
import aiyh.utils.tool.cn.hutool.core.lang.copier.Copier;
import aiyh.utils.tool.cn.hutool.core.util.ObjectUtil;
/**
*
*
* @param <S>
* @param <T>
* @author looly
* @since 5.8.0
*/
public abstract class AbsCopier<S, T> implements Copier<T> {
protected final S source;
protected final T target;
/**
*
*/
protected final CopyOptions copyOptions;
public AbsCopier(S source, T target, CopyOptions copyOptions) {
this.source = source;
this.target = target;
this.copyOptions = ObjectUtil.defaultIfNull(copyOptions, CopyOptions::create);
}
}

View File

@ -0,0 +1,94 @@
package aiyh.utils.tool.cn.hutool.core.bean.copier;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.lang.copier.Copier;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.Map;
/**
* Bean
*
* <pre>
* 1. Bean Bean
* 2. Bean Map
* 3. Map Bean
* 4. Map Map
* </pre>
*
* @author looly
*
* @param <T>
* @since 3.2.3
*/
public class BeanCopier<T> implements Copier<T>, Serializable {
private static final long serialVersionUID = 1L;
private final Copier<T> copier;
/**
* BeanCopier
*
* @param <T> Bean
* @param source BeanMap
* @param target Bean
* @param copyOptions
* @return BeanCopier
*/
public static <T> BeanCopier<T> create(Object source, T target, CopyOptions copyOptions) {
return create(source, target, target.getClass(), copyOptions);
}
/**
* BeanCopier
*
* @param <T> Bean
* @param source BeanMap
* @param target Bean
* @param destType Bean
* @param copyOptions
* @return BeanCopier
*/
public static <T> BeanCopier<T> create(Object source, T target, Type destType, CopyOptions copyOptions) {
return new BeanCopier<>(source, target, destType, copyOptions);
}
/**
*
*
* @param source BeanMap
* @param target Bean
* @param targetType Bean
* @param copyOptions
*/
public BeanCopier(Object source, T target, Type targetType, CopyOptions copyOptions) {
Assert.notNull(source, "Source bean must be not null!");
Assert.notNull(target, "Target bean must be not null!");
Copier<T> copier;
if (source instanceof Map) {
if (target instanceof Map) {
//noinspection unchecked
copier = (Copier<T>) new MapToMapCopier((Map<?, ?>) source, (Map<?, ?>) target, targetType, copyOptions);
} else {
copier = new MapToBeanCopier<>((Map<?, ?>) source, target, targetType, copyOptions);
}
}else if(source instanceof ValueProvider){
//noinspection unchecked
copier = new ValueProviderToBeanCopier<>((ValueProvider<String>) source, target, targetType, copyOptions);
} else {
if (target instanceof Map) {
//noinspection unchecked
copier = (Copier<T>) new BeanToMapCopier(source, (Map<?, ?>) target, targetType, copyOptions);
} else {
copier = new BeanToBeanCopier<>(source, target, targetType, copyOptions);
}
}
this.copier = copier;
}
@Override
public T copy() {
return copier.copy();
}
}

View File

@ -0,0 +1,91 @@
package aiyh.utils.tool.cn.hutool.core.bean.copier;
import aiyh.utils.tool.cn.hutool.core.bean.BeanUtil;
import aiyh.utils.tool.cn.hutool.core.bean.PropDesc;
import aiyh.utils.tool.cn.hutool.core.lang.Assert;
import aiyh.utils.tool.cn.hutool.core.util.TypeUtil;
import java.lang.reflect.Type;
import java.util.Map;
/**
* BeanBean
*
* @param <S> Bean
* @param <T> Bean
* @since 5.8.0
*/
public class BeanToBeanCopier<S, T> extends AbsCopier<S, T> {
/**
*
*/
private final Type targetType;
/**
*
*
* @param source Map
* @param target Bean
* @param targetType
* @param copyOptions
*/
public BeanToBeanCopier(S source, T target, Type targetType, CopyOptions copyOptions) {
super(source, target, copyOptions);
this.targetType = targetType;
}
@Override
public T copy() {
Class<?> actualEditable = target.getClass();
if (null != copyOptions.editable) {
// 检查限制类是否为target的父类或接口
Assert.isTrue(copyOptions.editable.isInstance(target),
"Target class [{}] not assignable to Editable class [{}]", actualEditable.getName(), copyOptions.editable.getName());
actualEditable = copyOptions.editable;
}
final Map<String, PropDesc> targetPropDescMap = BeanUtil.getBeanDesc(actualEditable).getPropMap(copyOptions.ignoreCase);
final Map<String, PropDesc> sourcePropDescMap = BeanUtil.getBeanDesc(source.getClass()).getPropMap(copyOptions.ignoreCase);
sourcePropDescMap.forEach((sFieldName, sDesc) -> {
if (null == sFieldName || false == sDesc.isReadable(copyOptions.transientSupport)) {
// 字段空或不可读,跳过
return;
}
sFieldName = copyOptions.editFieldName(sFieldName);
// 对key做转换转换后为null的跳过
if (null == sFieldName) {
return;
}
// 忽略不需要拷贝的 key,
if (false == copyOptions.testKeyFilter(sFieldName)) {
return;
}
// 检查目标字段可写性
final PropDesc tDesc = targetPropDescMap.get(sFieldName);
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {
// 字段不可写,跳过之
return;
}
// 检查源对象属性是否过滤属性
Object sValue = sDesc.getValue(this.source);
if (false == copyOptions.testPropertyFilter(sDesc.getField(), sValue)) {
return;
}
// 获取目标字段真实类型并转换源值
final Type fieldType = TypeUtil.getActualType(this.targetType, tDesc.getFieldType());
//sValue = Convert.convertWithCheck(fieldType, sValue, null, this.copyOptions.ignoreError);
sValue = this.copyOptions.convertField(fieldType, sValue);
sValue = copyOptions.editFieldValue(sFieldName, sValue);
// 目标赋值
tDesc.setValue(this.target, sValue, copyOptions.ignoreNullValue, copyOptions.ignoreError, copyOptions.override);
});
return this.target;
}
}

Some files were not shown because too many files have changed in this diff Show More