package net.techreadiness.persistence; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.Column; import javax.persistence.JoinColumn; import javax.persistence.MappedSuperclass; import javax.persistence.OneToMany; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlTransient; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang3.StringUtils; import com.fasterxml.jackson.annotation.JsonIgnore; import com.google.common.base.Function; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Maps; @MappedSuperclass public class BaseEntity { private transient Map<String, FieldInfo> fieldMap = null; @SuppressWarnings("rawtypes") private static LoadingCache<Class, List<PropertyDescriptor>> propertyCache = CacheBuilder.newBuilder().build( CacheLoader.from(new PropertyDescriptorLookup())); @XmlTransient @JsonIgnore public Map<String, FieldInfo> getColumnFieldInfo() { if (fieldMap == null) { fieldMap = new HashMap<>(); Field[] fields = this.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { String colName = fields[i].getName(); OneToMany oneToMany = fields[i].getAnnotation(OneToMany.class); // ManyToOne manyToOne = fields[i].getAnnotation(ManyToOne.class); Transient trans = fields[i].getAnnotation(Transient.class); String modifier = Modifier.toString(fields[i].getModifiers()); if (trans != null || oneToMany != null || StringUtils.contains(modifier, "static")) { continue; } JoinColumn joinColumn = fields[i].getAnnotation(JoinColumn.class); if (joinColumn != null && StringUtils.isNotBlank(joinColumn.name())) { colName = joinColumn.name(); } Column column = fields[i].getAnnotation(Column.class); if (column != null && StringUtils.isNotBlank(column.name())) { colName = column.name(); } FieldInfo fieldInfo = new FieldInfo(colName, fields[i].getType()); fieldMap.put(fields[i].getName(), fieldInfo); } } return fieldMap; } @XmlTransient @JsonIgnore public Map<String, String> getColumnsAsMap() { Map<String, String> colMap = Maps.newTreeMap(); Field[] fields = this.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { String colName = fields[i].getName(); Column annotation = fields[i].getAnnotation(Column.class); if (annotation != null) { try { colMap.put(colName, PropertyUtils.getProperty(this, colName).toString()); } catch (Exception e) { throw new RuntimeException(e); } } } return colMap; } @XmlTransient @JsonIgnore public Map<String, String> getAsMap() { Map<String, String> entityMap = Maps.newTreeMap(); try { for (PropertyDescriptor prop : propertyCache.get(this.getClass())) { String property = prop.getName(); String className = prop.getPropertyType().getName(); if (className.startsWith("java.util.") && !className.equals("java.util.Date") || className.startsWith("net.techreadiness") || "class".equals(property) || "asMap".equals(property) || "columnsAsMap".equals(property) || "columnFieldInfo".equals(property) || "extendedDefinition".equals(property) || "exts".equals(property) || "serviceObjectType".equals(property) || "extAttributes".equals(property)) { // TODO : I think we have to ignore this for now continue; } Object obj = prop.getReadMethod().invoke(this); entityMap.put(property, ConvertUtils.convert(obj)); } return entityMap; } catch (Exception e) { throw new RuntimeException(e); } } public class FieldInfo { private String colName; private Class<?> datatype; public FieldInfo(String colName, Class<?> datatype) { super(); this.colName = colName; this.datatype = datatype; } public String getColName() { return colName; } public void setColName(String colName) { this.colName = colName; } public Class<?> getDatatype() { return datatype; } public void setDatatype(Class<?> datatype) { this.datatype = datatype; } @Override public String toString() { return colName + "(" + datatype + ")"; } } @SuppressWarnings("rawtypes") public static class PropertyDescriptorLookup implements Function<Class, List<PropertyDescriptor>> { @Override public List<PropertyDescriptor> apply(Class clazz) { return Arrays.asList(PropertyUtils.getPropertyDescriptors(clazz)); } } }