io.xream.sqli.util.ParserUtil Maven / Gradle / Ivy
/*
* Copyright 2020 io.xream.sqli
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.xream.sqli.util;
import io.xream.sqli.annotation.X;
import io.xream.sqli.builder.SqlScript;
import io.xream.sqli.exception.ParsingException;
import io.xream.sqli.parser.BeanElement;
import io.xream.sqli.parser.Parsed;
import io.xream.sqli.parser.Parser;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
/**
* @Author Sim
*/
public final class ParserUtil {
public final static String SQL_KEYWORD_MARK = "`";
private ParserUtil() {
super();
}
private static void parseFieldsOfElementList(Class clz, Map filterMap, Map allMap) {
List fl = new ArrayList<>();
if (clz.getSuperclass() != Object.class) {
fl.addAll(Arrays.asList(clz.getSuperclass().getDeclaredFields()));
}
fl.addAll(Arrays.asList(clz.getDeclaredFields()));
/*
* 排除transient
*/
for (Field f : fl) {
allMap.put(f.getName(), f);
if (f.getModifiers() >= 128) {
filterMap.put(f.getName(), f);
}
/*
* ignored anno
*/
X.Ignore p = f.getAnnotation(X.Ignore.class);
if (p != null) {
filterMap.put(f.getName(), f);
}
}
}
private static void parseMethodsOfElementList(Class clz, Set mns, List methodList) {
if (clz.getSuperclass() != Object.class) {
methodList.addAll(Arrays.asList(clz.getSuperclass().getDeclaredMethods()));
}
methodList.addAll(Arrays.asList(clz.getDeclaredMethods())); // 仅仅XxxMapped子类
for (Method m : methodList) {
mns.add(m.getName());
}
}
private static void parseFilterListOfElementList(List filterList, Set mns, List ml) {
for (Method m : ml) {
String name = m.getName();
if (!(name.startsWith("set") || name.startsWith("get") || name.startsWith("is")))
continue;
String key = BeanUtil.getProperty(name);
BeanElement be = null;
for (BeanElement b : filterList) {
if (b.getProperty().equals(key)) {
be = b;
break;
}
}
if (be == null) {
be = new BeanElement();
be.setProperty(key);
filterList.add(be);
}
if (name.startsWith("set")) {
be.setSetter(name);
} else if (name.startsWith("get")) {
be.setGetter(name);
be.setClz(m.getReturnType());
} else if (name.startsWith("is")) {
be.setGetter(name);
be.setClz(m.getReturnType());
be.setProperty(name);
String setter = BeanUtil.getSetter(name); // FIXME 可能有BUG
if (mns.contains(setter)) {
be.setSetter(setter);
}
}
}
}
private static void filterElementList(List filterList, Map filterMap) {
/*
* 找出有setter 和 getter的一对
*/
Iterator ite = filterList.iterator();
while (ite.hasNext()) {// BUG, 这里去掉了boolen属性
BeanElement be = ite.next();
if (!be.isPair()) {
ite.remove();
}
}
/*
* 去掉transient
*/
for (String key : filterMap.keySet()) {
Iterator beIte = filterList.iterator();
while (beIte.hasNext()) {
BeanElement be = beIte.next();
if (be.getProperty().equals(key)) {
beIte.remove();
break;
}
}
}
}
private static List buildElementList(Class clz, List filterList, Map allMap) {
List list = new ArrayList();
for (BeanElement element : filterList) {
parseAnno(clz, element, allMap.get(element.getProperty()));
Class ec = element.getClz();
if (element.getSqlType() == null) {
if (ec == int.class || ec == Integer.class) {
element.setSqlType(SqlFieldType.INT);
element.setLength(11);
} else if (ec == long.class || ec == Long.class) {
element.setSqlType(SqlFieldType.LONG);
element.setLength(13);
} else if (ec == double.class || ec == Double.class) {
element.setSqlType(SqlFieldType.DOUBLE);
element.setLength(13);
} else if (ec == float.class || ec == Float.class) {
element.setSqlType(SqlFieldType.FLOAT);
element.setLength(13);
} else if (ec == boolean.class || ec == Boolean.class) {
element.setSqlType(SqlFieldType.BYTE);
element.setLength(1);
} else if (ec == String.class) {
element.setSqlType(SqlFieldType.VARCHAR);
if (element.getLength() == 0)
element.setLength(60);
} else if (ec == BigDecimal.class) {
element.setSqlType(SqlFieldType.DECIMAL);
} else if (ec == LocalDateTime.class || ec == LocalDate.class || ec == Date.class || ec == java.sql.Date.class || ec == Timestamp.class ) {
element.setSqlType(SqlFieldType.DATE);
} else if (EnumUtil.isEnum(ec)) {
element.setSqlType(SqlFieldType.VARCHAR);
if (element.getLength() == 0)
element.setLength(20);
} else {
element.setJson(true);
if (ec == List.class) {
Field field = null;
try {
field = clz.getDeclaredField(element.getProperty());
} catch (Exception e) {
e.printStackTrace();
}
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class geneType = (Class) pt.getActualTypeArguments()[0];
element.setGeneType(geneType);
}
element.setSqlType(SqlFieldType.VARCHAR);
if (element.getLength() == 0)
element.setLength(512);
}
} else if (element.getSqlType().contains(SqlFieldType.TEXT)) {
element.setLength(0);
} else {
element.setSqlType(SqlFieldType.VARCHAR);
}
list.add(element);
}
return list;
}
private static void initMethodCache(Class clz, List list) {
try {
for (BeanElement be : list) {
try {
be.setSetMethod(clz.getDeclaredMethod(be.getSetter(), be.getClz()));
} catch (NoSuchMethodException e) {
be.setSetMethod(clz.getSuperclass().getDeclaredMethod(be.getSetter(), be.getClz()));
}
try {
be.setGetMethod(clz.getDeclaredMethod(be.getGetter()));
} catch (NoSuchMethodException e) {
be.setGetMethod(clz.getSuperclass().getDeclaredMethod(be.getGetter()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("rawtypes")
public static List parseElementList(Class clz) {
Map filterMap = new HashMap<>();
Map allMap = new HashMap<>();
parseFieldsOfElementList(clz, filterMap, allMap); //Step 1
Set mns = new HashSet<>();
List ml = new ArrayList<>();
parseMethodsOfElementList(clz, mns, ml);
List filterList = new ArrayList<>();
parseFilterListOfElementList(filterList, mns, ml);
filterElementList(filterList, filterMap);
List list = buildElementList(clz, filterList, allMap);
initMethodCache(clz, list);
return list;
}
public static void parseCacheableAnno(Class clz, Parsed parsed) {
X.NoCache p = (X.NoCache) clz.getAnnotation(X.NoCache.class);
if (p != null) {
parsed.setNoCache(true);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static void parseAnno(Class clz, BeanElement ele, Field f) {
Method m = null;
try {
m = clz.getDeclaredMethod(ele.getGetter());
} catch (NoSuchMethodException e) {
}
if (m != null) {
X p = m.getAnnotation(X.class);
if (p != null) {
ele.setLength(p.length());
}
}
if (f != null) {
X p = f.getAnnotation(X.class);
if (p != null) {
ele.setLength(p.length());
}
X.Mapping mapping = f.getAnnotation(X.Mapping.class);
if (mapping != null && SqliStringUtil.isNotNull(mapping.value())) {
ele.setMapper(mapping.value());
}
}
}
@SuppressWarnings({"rawtypes"})
public static void parseKey(Parsed parsed, Class clz) {
List list = new ArrayList<>();
try {
list.addAll(Arrays.asList(clz.getDeclaredFields()));
Class sc = clz.getSuperclass();
if (sc != Object.class) {
list.addAll(Arrays.asList(sc.getDeclaredFields()));
}
} catch (Exception e) {
}
for (Field f : list) {
X.Key a = f.getAnnotation(X.Key.class);
if (a != null) {
f.setAccessible(true);
parsed.setKeyField(f);
}
}
}
public static void parseTagAndSub(Parsed parsed, Class clz) {
List list = new ArrayList<>();
try {
list.addAll(Arrays.asList(clz.getDeclaredFields()));
Class sc = clz.getSuperclass();
if (sc != Object.class) {
list.addAll(Arrays.asList(sc.getDeclaredFields()));
}
} catch (Exception e) {
}
for (Field f : list) {
X.Tag t = f.getAnnotation(X.Tag.class);
if (t != null) {
f.setAccessible(true);
parsed.getTagFieldList().add(f);
}
X.TagTarget tt = f.getAnnotation(X.TagTarget.class);
if (tt != null) {
f.setAccessible(true);
if (parsed.getTagKeyField() != null)
throw new ParsingException("find another annotation: X.TagTarget, class: " + clz);
parsed.setTagKeyField(f);
}
}
}
public static String filterSQLKeyword(String mapper) {
for (String keyWord : SqlScript.KEYWORDS) {
if (keyWord.equalsIgnoreCase(mapper)) {
return SQL_KEYWORD_MARK + mapper + SQL_KEYWORD_MARK;
}
}
return mapper;
}
public static String getClzName(String alia, Map aliaMap) {
String a = aliaMap.get(alia);
if (SqliStringUtil.isNotNull(a))
return a;
return alia;
}
public static Object tryToGetId(T t, Parsed parsed) {
Field f = parsed.getKeyField();
Object id = null;
try {
id = f.get(t);
} catch (Exception e) {
}
if (id == null)
throw new IllegalArgumentException("obj keyOne = " + id + ", " + t);
return id;
}
public static String getCacheKey(Object obj, Parsed parsed) {
try {
Object keyOneObj = tryToGetId(obj, parsed);
if (keyOneObj != null)
return keyOneObj.toString();
} catch (Exception e) {
}
return null;
}
public static String getMapper(String property) {
String AZ = "AZ";
int min = AZ.charAt(0) - 1;
int max = AZ.charAt(1) + 1;
try {
String spec = Parser.mappingSpec;
if (SqliStringUtil.isNotNull(spec)) {
char[] arr = property.toCharArray();
int length = arr.length;
List list = new ArrayList();
StringBuilder temp = new StringBuilder();
for (int i = 0; i < length; i++) {
char c = arr[i];
if (c > min && c < max) {
String ts = temp.toString();
if (SqliStringUtil.isNotNull(ts)) {
list.add(temp.toString());
}
temp = new StringBuilder();
String s = String.valueOf(c);
temp.append(s.toLowerCase());
} else {
temp = temp.append(c);
}
if (i == length - 1) {
list.add(temp.toString());
}
}
String str = "";
int size = list.size();
for (int i = 0; i < size; i++) {
String s = list.get(i);
str += s;
if (i < size - 1) {
str += "_";
}
}
return str;
}
} catch (Exception e) {
}
return property;
}
public interface SqlFieldType {
String TEXT = "text";
String VARCHAR = "varchar";
String DATE = "timestamp";
String INT = "int";
String LONG = "bigint";
String BYTE = "tinyint";
String DOUBLE = "float";//float
String FLOAT = "float";//real
String DECIMAL = "decimal";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy