package net.sf.minuteProject.configuration.bean.enrichment.convention;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import net.sf.minuteProject.configuration.bean.BusinessModel;
import net.sf.minuteProject.configuration.bean.enrichment.Entity;
import net.sf.minuteProject.configuration.bean.enrichment.Field;
import net.sf.minuteProject.configuration.bean.model.data.Column;
import net.sf.minuteProject.configuration.bean.model.data.Database;
import net.sf.minuteProject.configuration.bean.model.data.Table;
import net.sf.minuteProject.utils.ForeignKeyUtils;
import net.sf.minuteProject.utils.TableUtils;
public class ForeignKeyConvention extends ModelConvention {
public static final String AUTODETECT_FOREIGN_KEY_BASED_ON_TARGET_PRIMARY_KEY_NAME = "autodetect-foreign-key-based-on-target-primary-key-name";
// public static final String APPLY_DEFAULT_FK_BY_ENTITY_NAME_AND_SUFFIX = "apply-default-foreign-key-by-entity-name-and-suffix";
public static final String AUTODETECT_FOREIGN_KEY_BASED_ON_SIMILARITY_AND_MAP = "autodetect-foreign-key-based-on-similarity-and-map";
public String defaultSuffix, columnEnding, columnStarting;
private String fieldPatternType;
public String getFieldPatternType() {
return fieldPatternType;
}
public void setFieldPatternType(String fieldPatternType) {
this.fieldPatternType = fieldPatternType;
}
public String getDefaultSuffix() {
return defaultSuffix;
}
public void setDefaultValue(String defaultValue) {
this.defaultSuffix = defaultValue;
}
public void setDefaultSuffix(String defaultSuffix) {
this.defaultSuffix = defaultSuffix;
}
public String getColumnEnding() {
return columnEnding;
}
public void setColumnEnding(String columnEnding) {
this.columnEnding = columnEnding;
}
public String getColumnStarting() {
return columnStarting;
}
public void setColumnStarting(String columnStarting) {
this.columnStarting = columnStarting;
}
@Override
public void apply(BusinessModel model) {
if (AUTODETECT_FOREIGN_KEY_BASED_ON_SIMILARITY_AND_MAP.equals(type)) {
if (model.getBusinessPackage() != null) {
for (Table table : model.getBusinessPackage().getEntities()) {
applyEntitySimilarity(table);
}
}
}
if (AUTODETECT_FOREIGN_KEY_BASED_ON_TARGET_PRIMARY_KEY_NAME.equals(type)) {
if (model.getBusinessPackage() != null) {
Map<String, Table> map = TableUtils.getPrimaryKeyTableMap(model);
for (Table table : model.getBusinessPackage().getEntities()) {
applyFieldSimilarity(table, map);
}
}
}
}
private void applyEntitySimilarity(Table table) {
for (Field field : getForeignKeyFieldsNotInSelfReferencedPrimaryKey(table)){
ForeignKeyUtils.setForeignKey(table, field);
}
}
private void applyFieldSimilarity(Table table, Map<String, Table> map) {
//foreach column get name
// check according to patterntype if it is to
for (Column column : table.getAttributes()) {
Table target = matchTable(column, map);
if (target!=null) {
Field field = getForeignKeyField(column, table, target);
ForeignKeyUtils.setForeignKey(table, field);
}
}
}
private Table matchTable(Column column, Map<String, Table> map) {
for (Entry<String, Table> entry : map.entrySet()) {
if (matchEntry(column, entry.getKey())) {
return entry.getValue();
}
}
return null;
}
private boolean matchEntry(Column column, String key) {
return net.sf.minuteProject.utils.StringUtils.checkExpression(column.getName(), fieldPatternType, key);
}
private List<Field> getForeignKeyFieldsNotInSelfReferencedPrimaryKey(Table table) {
List<Field> list = new ArrayList<Field>();
for (Column column : table.getColumns()) {
if (isConventionToApply(column)) { //
Field f = getForeignKeyField(column, table);
if (f != null) {
list.add(f);
}
}
}
return list;
}
private boolean isSelfReferencePrimaryKey(Column column) {
if (column.isPrimaryKey()) {
Table target = getTarget(column);
if (target!=null &&
target.getName().toLowerCase().equals(column.getTable().getName().toLowerCase()))
return true;
}
return false;
}
private Table getTarget(Column column) {
Table table = column.getTable();
String tablename = getTargetEntityNameLowerCase(column);
Table target = TableUtils.getTable(table.getDatabase(), tablename);
if (target == null) {
target = TableUtils.getTableFromAlias(table.getDatabase(), tablename);
}
return target;
}
private Field getForeignKeyField(Column column, Table table) {
// if (column.isPrimaryKey() && !table.isManyToMany()) return null;
// String tablename = getTargetEntityName(column);
// Table target = TableUtils.getTable(table.getDatabase(), tablename);
// if (target == null)
// target = TableUtils.getTableFromAlias(table.getDatabase(), tablename);
Table target = getTarget(column);
return getForeignKeyField(column, table, target);
}
private Field getForeignKeyField(Column column, Table table, Table target) {
if (target != null) {
Field f = new Field();
f.setName(column.getName());
f.setLinkToTargetEntity(target.getName());
f.setLinkToTargetField(TableUtils.getPrimaryKey(target));
Entity entity = new Entity();
entity.setName(table.getName());
f.setEntity(entity);
f.setBidirectional("true");
return f;
}
return null;
}
private String getTargetEntityNameLowerCase(Column column) {
String key = column.getName().toLowerCase();
if (columnEnding != null && !"".equals(columnEnding))
key = StringUtils.stripEnd(key, columnEnding);
if (columnStarting != null && !"".equals(columnStarting))
key = StringUtils.stripStart(key, columnStarting);
return key;
}
private boolean isConventionToApply(Column column) {
if (isSelfReferencePrimaryKey(column)) return false;
return isConventionToApplyOnPatternRelevance(column);
}
private boolean isConventionToApplyOnPatternRelevance(Column column) {
if ((columnEnding == null || "".equals(columnEnding)) &&
(columnStarting == null || "".equals(columnStarting))) return false;
String key = getTargetEntityNameLowerCase(column);
if (key.equals(column.getName().toLowerCase())) {
return false;
}
Table target = getTarget(column);
if (target==null)
return false;
String targetType = TableUtils.getPrimaryKeyType(target);
if (!targetType.equals(column.getType()))
return false;
return true;
}
}