001package gudusoft.gsqlparser.dlineage.util;
002
003import gudusoft.gsqlparser.util.json.JSONException;
004import gudusoft.gsqlparser.util.json.JSONField;
005
006import java.beans.IntrospectionException;
007import java.beans.Introspector;
008import java.beans.PropertyDescriptor;
009import java.lang.reflect.Field;
010import java.util.*;
011
012@SuppressWarnings("rawtypes")
013public abstract class BeanUtil {
014
015        private static final Map<String, PropertyDescriptor[]> cacheDescriptors = new WeakHashMap<>();
016
017        @SuppressWarnings("unchecked")
018        public static LinkedHashMap<String, Object> bean2Map(Object src) {
019                if (src instanceof LinkedHashMap) {
020                        return (LinkedHashMap<String, Object>) src;
021                }
022                if (src instanceof Map) {
023                        return new LinkedHashMap<>((Map) src);
024                }
025
026                try {
027                        LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
028                        String typeName = src.getClass().getCanonicalName();
029                        if (!cacheDescriptors.containsKey(typeName)) {
030                                Map<String, Integer> fieldOrder = buildFieldOrder(src.getClass());
031                                PropertyDescriptor[] allDescriptors = Introspector.getBeanInfo(src.getClass()).getPropertyDescriptors();
032                                List<PropertyDescriptor> validDescriptors = new ArrayList<>();
033                                for (PropertyDescriptor pd : allDescriptors) {
034                                        if (!"class".equals(pd.getName()) && pd.getReadMethod() != null) {
035                                                validDescriptors.add(pd);
036                                        }
037                                }
038                                validDescriptors.sort(new Comparator<PropertyDescriptor>() {
039                                        @Override
040                                        public int compare(PropertyDescriptor o1, PropertyDescriptor o2) {
041                                                return compareOrder(fieldOrder, o1.getName(), o2.getName());
042                                        }
043                                });
044                                cacheDescriptors.put(typeName, validDescriptors.toArray(new PropertyDescriptor[0]));
045                        }
046
047                        for (PropertyDescriptor pd : cacheDescriptors.get(typeName)) {
048                                try {
049                                        JSONField jsonField = pd.getReadMethod().getAnnotation(JSONField.class);
050                                        if (jsonField != null && !jsonField.serialize()) {
051                                                continue;
052                                        }
053                                        Object value = pd.getReadMethod().invoke(src);
054                                        if (value == null) {
055                                                continue;
056                                        }
057                                        if (value instanceof Collection) {
058                                                List<Object> listValues = new ArrayList<>();
059                                                for (Object item : (Collection) value) {
060                                                        if (item instanceof String) {
061                                                                listValues.add(item);
062                                                        } else {
063                                                                listValues.add(bean2Map(item));
064                                                        }
065                                                }
066                                                resultMap.put(pd.getName(), listValues);
067                                        } else if (value.getClass().isMemberClass()) {
068                                                resultMap.put(pd.getName(), bean2Map(value));
069                                        } else {
070                                                resultMap.put(pd.getName(), value);
071                                        }
072                                } catch (Exception ex) {
073                                        throw new JSONException(ex);
074                                }
075                        }
076                        return resultMap;
077                } catch (IntrospectionException e) {
078                        throw new JSONException(e);
079                }
080        }
081
082        private static Map<String, Integer> buildFieldOrder(Class target) {
083                Map<String, Integer> orderMap = new HashMap<>();
084                for (Field f : target.getDeclaredFields()) {
085                        orderMap.put(f.getName(), orderMap.size());
086                }
087                return orderMap;
088        }
089
090        private static int compareOrder(Map<String, Integer> orderMap, String n1, String n2) {
091                if (orderMap.containsKey(n1) && orderMap.containsKey(n2)) {
092                        return orderMap.get(n1).compareTo(orderMap.get(n2));
093                }
094                return 0;
095        }
096}