All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dieselpoint.norm.PojoInfo Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
package com.dieselpoint.norm;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;

/**
 * Provides means of reading and writing properties in a pojo.
 */
public class PojoInfo {
	
	/*
	 * annotations recognized: @ Id, @ GeneratedValue @ transient @ table
	 */

	private LinkedHashMap propertyMap = new LinkedHashMap();
	private String table;
	private String primaryKeyName;
	private String generatedColumnName;
	//private String [] columns;
	//private String commaColumns;
	
	private String insertSql;
	private int insertSqlArgCount;
	private String [] insertColumnNames;
	private String selectColumns;
	private String updateSql;
	private String[] updateColumnNames;
	private int updateSqlArgCount;
	
	static class Property {
		String name;
		Method readMethod;
		Method writeMethod;
		Field field;
		Class dataType;
		boolean isGenerated;
		boolean isPrimaryKey;
		boolean isEnumField;
		Class enumClass;
	}

	public PojoInfo(Class clazz) throws IntrospectionException {
	    
	    for (Field field: clazz.getFields()) {
	    	if (Modifier.isPublic(field.getModifiers())) {
	    		
	    		if (field.getAnnotation(Transient.class) != null) {
	    			continue;
	    		}
	    		
	    		Property pair = new Property();
	            pair.name = field.getName();
	            pair.field = field;
	            pair.dataType = field.getType();
	    		
	    		if (field.getAnnotation(Id.class) != null) {
	    			pair.isPrimaryKey = true;
	    			primaryKeyName = field.getName();
	    		}
	    		
	    		if (field.getAnnotation(GeneratedValue.class) != null) {
	    			generatedColumnName = field.getName();
	    			pair.isGenerated = true;
	    		}
	            
	    		if (field.getType().isEnum()) {
	    			pair.isEnumField = true;
	    			pair.enumClass = (Class) field.getType();
	    		}
	    		
	            propertyMap.put(pair.name, pair);
	    	}
	    }

		BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
	    PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
		for (PropertyDescriptor descriptor : descriptors) {
            String name = descriptor.getName();
            Property pair = new Property();
            pair.name = name;
            pair.readMethod = getMethod(descriptor.getReadMethod(), name, pair);
            pair.writeMethod = getMethod(descriptor.getWriteMethod(), name, pair);
            pair.dataType = descriptor.getPropertyType();
            propertyMap.put(name, pair);
		}
		
		Table annot = (Table) clazz.getAnnotation(Table.class);
		if (annot != null) {
			table = annot.name();
		} else {
			table = clazz.getSimpleName();
		}
		
		makeInsertSql();
		makeUpdateSql();
		makeSelectColumns();
	}
	
	/*
	private void makeColumns() {
		columns = new String [map.size()];
		map.keySet().toArray(columns);
		StringBuilder buf = new StringBuilder();
		for (int i = 0; i < columns.length; i++) {
			if (buf.length() > 0) {
				buf.append(',');
			}
			buf.append(columns[i]);
		}
		commaColumns = buf.toString();
	}
	*/

	private Method getMethod(Method meth, String propertyName, Property pair) {
		if (meth == null) {
			return null;
		}
		if (meth.getAnnotation(Transient.class) != null) {
			return null;
		}
		if (meth.getAnnotation(Id.class) != null) {
			this.primaryKeyName = propertyName;
			pair.isPrimaryKey = true;
		}
		if (meth.getAnnotation(GeneratedValue.class) != null) {
			this.generatedColumnName = propertyName;
			pair.isGenerated = true;
		}
		return meth;
	}

	public Object getValue(Object pojo, String name) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Property prop = propertyMap.get(name);
		if (prop == null) {
			throw new NoSuchFieldException(name);
		}
		
		if (prop.readMethod != null) {
			return prop.readMethod.invoke(pojo);
		}
		
		if (prop.isEnumField) {
			// convert all enums to string
			Object o = prop.field.get(pojo);
			if (o == null) {
				return null;
			} else {
				return o.toString();
			}
		}
		
		if (prop.field != null) {
			return prop.field.get(pojo);
		}
		return null;
	}
	
	
	public void putValue(Object pojo, String name, Object value) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Property pair = propertyMap.get(name);
		if (pair == null) {
			throw new NoSuchFieldException(name);
		}
		
		if (pair.writeMethod != null) {
			pair.writeMethod.invoke(pojo, value);
			return;
		}
		
		if (pair.field != null) {
			Object val = value;
			
			if (pair.isEnumField) {
				// convert to enum const
				val = getEnumConst(pair.enumClass, value.toString());
			}
			
			pair.field.set(pojo, val);
			return;
		}
	}

	private > Object getEnumConst(Class enumType, String o) {
		return Enum.valueOf(enumType, o);
	}

	public String getTable() {
		return table;
	}

	public Collection getProperties() {
		return propertyMap.values();
	}
	
	public Property getProperty(String columnName) {
		return propertyMap.get(columnName);
	}

	public String getPrimaryKeyName() {
		return primaryKeyName;
	}

	//public String[] getColumns() {
	//	return columns;
	//}

	//public String getCommaColumns() {
	//	return commaColumns;
	//}

	public String getGeneratedColumnName() {
		return generatedColumnName;
	}

	private void makeInsertSql() {
		
		ArrayList cols = new ArrayList();
		for (Property prop: propertyMap.values()) {
			if (prop.isGenerated) {
				continue;
			}
			cols.add(prop.name);
		}
		insertColumnNames = cols.toArray(new String [cols.size()]);
		insertSqlArgCount = insertColumnNames.length;
		
		StringBuilder buf = new StringBuilder();
		buf.append("insert into ");
		buf.append(getTable());
		buf.append(" (");
		buf.append(Util.join(insertColumnNames)); // comma sep list?
		buf.append(") values (");
		buf.append(Util.getQuestionMarks(insertSqlArgCount));
		buf.append(")");
		
		insertSql = buf.toString();
	}
	
	private void makeUpdateSql() {
		
		ArrayList cols = new ArrayList();
		for (Property prop: propertyMap.values()) {
			
			if (prop.isPrimaryKey) {
				continue;
			}
			
			if (prop.isGenerated) {
				continue;
			}
			
			cols.add(prop.name);
		}
		updateColumnNames = cols.toArray(new String [cols.size()]);
		updateSqlArgCount = updateColumnNames.length + 1; // + 1 for the where arg
		
		StringBuilder buf = new StringBuilder();
		buf.append("update ");
		buf.append(getTable());
		buf.append(" set ");

		for (int i = 0; i < cols.size(); i++) {
			if (i > 0) {
				buf.append(',');
			}
			buf.append(cols.get(i) + "=?");
		}
		buf.append(" where " + primaryKeyName + "=?");
		
		updateSql = buf.toString();
	}


	public Object[] getInsertArgs(Object row) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Object [] args = new Object[insertSqlArgCount];
		for (int i = 0; i < insertSqlArgCount; i++) {
			args[i] = getValue(row, insertColumnNames[i]);
		}
		return args;
	}

	public Object[] getUpdateArgs(Object row) throws NoSuchFieldException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Object [] args = new Object[updateSqlArgCount];
		for (int i = 0; i < updateSqlArgCount - 1; i++) {
			args[i] = getValue(row, updateColumnNames[i]);
		}
		// add the value for the where clause to the end
		Object pk = getValue(row, primaryKeyName);
		args[updateSqlArgCount - 1] = pk;
		return args;
	}
	
	
	public String getInsertSql() {
		return insertSql;
	}

	private void makeSelectColumns() {
		ArrayList cols = new ArrayList();
		for (Property prop: propertyMap.values()) {
			cols.add(prop.name);
		}
		selectColumns = Util.join(cols);
	}
	
	
	public String getSelectColumns() {
		return selectColumns;
	}

	public String getUpdateSql() {
		return updateSql;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy