com.jpattern.orm.mapper.clazz.ClassMapBuilder Maven / Gradle / Ivy
package com.jpattern.orm.mapper.clazz;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jpattern.orm.annotation.Generator;
import com.jpattern.orm.annotation.Id;
import com.jpattern.orm.annotation.Ignore;
import com.jpattern.orm.annotation.column.ColumnInfoFactory;
import com.jpattern.orm.annotation.generator.GeneratorInfoFactory;
import com.jpattern.orm.annotation.table.TableInfo;
import com.jpattern.orm.annotation.table.TableInfoFactory;
import com.jpattern.orm.annotation.version.VersionInfoFactory;
import com.jpattern.orm.exception.OrmConfigurationException;
import com.jpattern.orm.persistor.reflection.FieldGetManipulator;
import com.jpattern.orm.persistor.reflection.FieldSetManipulator;
import com.jpattern.orm.persistor.reflection.GetManipulator;
import com.jpattern.orm.persistor.reflection.GetterGetManipulator;
import com.jpattern.orm.persistor.reflection.SetManipulator;
import com.jpattern.orm.persistor.reflection.SetterSetManipulator;
import com.jpattern.orm.util.FieldDefaultNaming;
/**
*
* @author Francesco Cina
*
* 22/mag/2011
*/
public class ClassMapBuilder implements IClassMapBuilder {
private final Class clazz;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public ClassMapBuilder(final Class clazz) {
this.clazz = clazz;
}
/* (non-Javadoc)
* @see com.jpattern.orm.mapper.IClassMapperGenerator#generate()
*/
@Override
public IClassMap generate() {
this.logger.info("generate " + IClassMap.class.getSimpleName() + " for Class " + this.clazz.getName());
TableInfo tableInfo = TableInfoFactory.getTableInfo(this.clazz);
this.logger.info("table name expected in relation with class " + this.clazz.getSimpleName() + ": " + tableInfo.getTableName() + " - schema: " + tableInfo.getSchemaName());
final ClassMap classMap = new ClassMap(this.clazz, tableInfo);
this.initializeClassFields(classMap);
this.initializeColumnNames(classMap);
return classMap ;
}
private void initializeClassFields(final ClassMap classMap) {
final List methods = Arrays.asList( this.clazz.getMethods() );
final List fields = this.getAllInheritedFields(this.clazz);
for (Field field : fields) {
if (!field.isAnnotationPresent(Ignore.class) && !Modifier.isStatic( field.getModifiers() ) ) {
classMap.addClassField(this.buildClassField(field, methods, field.getType()));
}
}
}
private ClassField buildClassField(final Field field, final List methods, final Class fieldClass) {
ClassField classField = new ClassField(fieldClass, field.getName());
classField.setColumnInfo( ColumnInfoFactory.getColumnInfo(field) );
classField.setGeneratorInfo(GeneratorInfoFactory.getGeneratorInfo(field));
classField.setIdentifier(field.isAnnotationPresent(Id.class));
classField.setVersionInfo(VersionInfoFactory.getVersionInfo(field));
classField.setGetManipulator(this.getGetManipulator(field, methods, fieldClass));
classField.setSetManipulator(this.getSetManipulator(field, methods, fieldClass));
this.logger.info( "DB column [" + classField.getColumnInfo().getDBColumnName() + "]" + " will be associated with object field [" + classField.getFieldName() + "]");
return classField;
}
private GetManipulator getGetManipulator(final Field field, final List methods, final Class clazz) {
Method getter = null;
String getterName = "";
for (final Method method : methods) {
if (FieldDefaultNaming.getDefaultGetterName(field.getName()).equals(method.getName())) {
getter = method;
getterName = method.getName();
}
if (FieldDefaultNaming.getDefaultBooleanGetterName(field.getName()).equals(method.getName())) {
getter = method;
getterName = method.getName();
}
}
this.logger.info("getter for property [" + field.getName() + "]: [" + getterName + "]");
if ( getter != null) {
return new GetterGetManipulator(getter);
}
return new FieldGetManipulator(field);
}
private SetManipulator getSetManipulator(final Field field, final List methods, final Class clazz) {
Method setter = null;
String setterName = "";
for (final Method method : methods) {
if (FieldDefaultNaming.getDefaultSetterName(field.getName()).equals(method.getName())) {
setter = method;
setterName = method.getName();
}
}
this.logger.info("setter for property [" + field.getName() + "]: [" + setterName + "]");
if ( setter != null) {
return new SetterSetManipulator(setter);
}
return new FieldSetManipulator(field);
}
private void initializeColumnNames(final ClassMap classMap) {
this.logger.info("Start column analisys for Class " );
final List allColumnJavaNamesList = new ArrayList();
final List allNotGeneratedColumnJavaNamesList = new ArrayList();
final List allGeneratedColumnJavaNamesList = new ArrayList();
final List allGeneratedColumnDBNamesList = new ArrayList();
final List primaryKeyColumnJavaNamesList = new ArrayList();
final List primaryKeyAndVersionColumnJavaNamesList = new ArrayList();
final List notPrimaryKeyColumnJavaList = new ArrayList();
boolean hasGenerator = false;
for (final Entry> entry : classMap.getUnmodifiableFieldClassMap().entrySet()) {
final String javaFieldName = entry.getKey();
allColumnJavaNamesList.add(javaFieldName);
if( entry.getValue().isIdentifier() ) {
primaryKeyColumnJavaNamesList.add(javaFieldName);
primaryKeyAndVersionColumnJavaNamesList.add(javaFieldName);
this.logger.info("Field [" + javaFieldName + "] will be used as a Primary Key field");
} else {
notPrimaryKeyColumnJavaList.add(javaFieldName);
this.logger.info("Field [" + javaFieldName + "] will be used as a normal field");
}
if ( entry.getValue().getGeneratorInfo().isValid() ) {
if (!hasGenerator) {
allGeneratedColumnJavaNamesList.add(javaFieldName);
allGeneratedColumnDBNamesList.add(entry.getValue().getColumnInfo().getDBColumnName());
this.logger.info("Field [" + javaFieldName + "] is an autogenerated field");
hasGenerator=true;
}
else {
throw new OrmConfigurationException("A bean can have maximum one field annotated with @" + Generator.class.getSimpleName() + ". Error in class:[" + this.clazz.getCanonicalName() + "] field: [" + javaFieldName + "]");
}
} else {
allNotGeneratedColumnJavaNamesList.add(javaFieldName);
}
if ( entry.getValue().getVersionInfo().isVersionable() ) {
primaryKeyAndVersionColumnJavaNamesList.add(javaFieldName);
}
}
classMap.setAllColumnJavaNames( allColumnJavaNamesList.toArray(new String[0]) );
classMap.setAllNotGeneratedColumnJavaNames( allNotGeneratedColumnJavaNamesList.toArray(new String[0]) );
classMap.setAllGeneratedColumnJavaNames( allGeneratedColumnJavaNamesList.toArray(new String[0]) );
classMap.setAllGeneratedColumnDBNames( allGeneratedColumnDBNamesList.toArray(new String[0]) );
classMap.setNotPrimaryKeyColumnJavaNames( notPrimaryKeyColumnJavaList.toArray(new String[0]) );
classMap.setPrimaryKeyColumnJavaNames( primaryKeyColumnJavaNamesList.toArray(new String[0]) );
classMap.setPrimaryKeyAndVersionColumnJavaNames( primaryKeyAndVersionColumnJavaNamesList.toArray(new String[0]) );
}
private List getAllInheritedFields(final Class> type) {
final List fields = new ArrayList();
for (Class> c = type; c != null; c = c.getSuperclass()) {
fields.addAll(Arrays.asList(c.getDeclaredFields()));
}
return fields;
}
}