diff --git a/src/main/java/com/sjhy/plugin/dto/TableInfoSettingsDTO.java b/src/main/java/com/sjhy/plugin/dto/TableInfoSettingsDTO.java index 60a56ee..d8549f0 100644 --- a/src/main/java/com/sjhy/plugin/dto/TableInfoSettingsDTO.java +++ b/src/main/java/com/sjhy/plugin/dto/TableInfoSettingsDTO.java @@ -3,14 +3,18 @@ package com.sjhy.plugin.dto; import com.intellij.database.model.DasNamespace; import com.intellij.database.psi.DbElement; import com.intellij.database.psi.DbTable; +import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiClass; +import com.sjhy.plugin.dict.GlobalDict; import com.sjhy.plugin.entity.TableInfo; +import com.sjhy.plugin.tool.ReflectionUtils; import lombok.Data; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; +import java.util.TreeMap; /** * 表格信息设置传输对象 @@ -24,7 +28,7 @@ public class TableInfoSettingsDTO { private Map tableInfoMap; public TableInfoSettingsDTO() { - this.tableInfoMap = new HashMap<>(16); + this.tableInfoMap = new TreeMap<>(); } private String generateKey(DbTable dbTable) { @@ -39,9 +43,12 @@ public class TableInfoSettingsDTO { } builder.insert(0, name); try { - Method method = element.getClass().getDeclaredMethod("getParent"); + Method method = ReflectionUtils.getDeclaredMethod(element.getClass(), "getParent"); + if (method == null) { + break; + } element = (DbElement) method.invoke(element); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + } catch (IllegalAccessException | InvocationTargetException e) { break; } // 未必所有的数据库都是存在三层,例如MySQL就只有两层。如果上次层不是Namespace,则不再继续获取 @@ -101,6 +108,7 @@ public class TableInfoSettingsDTO { } else if (tableInfo.getPsiClassObj() != null) { key = generateKey((PsiClass) tableInfo.getPsiClassObj()); } else { + Messages.showInfoMessage(tableInfo.getName() + "表配置信息保存失败", GlobalDict.TITLE_INFO); return; } this.tableInfoMap.put(key, TableInfoDTO.valueOf(tableInfo)); diff --git a/src/main/java/com/sjhy/plugin/tool/ReflectionUtils.java b/src/main/java/com/sjhy/plugin/tool/ReflectionUtils.java index 3c7ed07..c38f85b 100644 --- a/src/main/java/com/sjhy/plugin/tool/ReflectionUtils.java +++ b/src/main/java/com/sjhy/plugin/tool/ReflectionUtils.java @@ -1,7 +1,13 @@ package com.sjhy.plugin.tool; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; /** * 反射工具 @@ -25,4 +31,59 @@ public class ReflectionUtils { } } + public static Method getDeclaredMethod(Class clazz, String name, Class... parameterTypes) { + Class searchType = clazz; + while (searchType != null) { + Method[] methods = (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType)); + for (Method method : methods) { + if (!Objects.equals(name, method.getName())) { + continue; + } + if (parameterTypes == null || Arrays.equals(parameterTypes, method.getParameterTypes())) { + return method; + } + } + searchType = searchType.getSuperclass(); + } + return null; + } + + private static Method[] getDeclaredMethods(Class clazz) { + Method[] result; + try { + Method[] declaredMethods = clazz.getDeclaredMethods(); + List defaultMethods = findConcreteMethodsOnInterfaces(clazz); + if (defaultMethods != null) { + result = new Method[declaredMethods.length + defaultMethods.size()]; + System.arraycopy(declaredMethods, 0, result, 0, declaredMethods.length); + int index = declaredMethods.length; + for (Method defaultMethod : defaultMethods) { + result[index] = defaultMethod; + index++; + } + } else { + result = declaredMethods; + } + } catch (Throwable ex) { + throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() + + "] from ClassLoader [" + clazz.getClassLoader() + "]", ex); + } + return result; + } + + private static List findConcreteMethodsOnInterfaces(Class clazz) { + List result = null; + for (Class ifc : clazz.getInterfaces()) { + for (Method ifcMethod : ifc.getMethods()) { + if (!Modifier.isAbstract(ifcMethod.getModifiers())) { + if (result == null) { + result = new ArrayList<>(); + } + result.add(ifcMethod); + } + } + } + return result; + } + }