name = pks[0].getName();
}
// if we can't adapt, then the user must at least give a column name
if (name == null && !adapt && !fill)
throw new MetaDataException(_loc.get(prefix + "-no-fkcol-name",
context));
// check to see if the column isn't in the expected table; it might
// be an inverse join or a join to a base class of the target type
Table local = table;
Table foreign = rel.getTable();
boolean fullName = false;
boolean inverse = false;
if (name != null) {
int dotIdx = name.lastIndexOf('.');
if (dotIdx != -1) {
// allow use of '.' without prefix to mean "use expected
// foreign table"
if (dotIdx == 0)
local = foreign;
else
local = findTable(context, name.substring(0, dotIdx),
local, foreign, null);
fullName = true;
name = name.substring(dotIdx + 1);
// if inverse join, then swap local and foreign tables
if (local != table) {
foreign = table;
inverse = true;
}
}
}
boolean forceInverse = !fullName && _join == JOIN_INVERSE;
if (forceInverse) {
local = foreign;
foreign = table;
inverse = true;
}
// determine target
String targetName = given.getTarget();
Object target = null;
Table ttable = null;
boolean constant = false;
boolean fullTarget = false;
if (targetName == null && given.getTargetField() != null) {
ClassMapping tcls = (inverse) ? cls : rel;
String fieldName = given.getTargetField();
int dotIdx = fieldName.lastIndexOf('.');
fullTarget = dotIdx != -1;
if (dotIdx == 0) {
// allow use of '.' without prefix to mean "use expected local
// cls"; but if we already inversed no need to switch again
if (!inverse)
tcls = cls;
fieldName = fieldName.substring(1);
} else if (dotIdx > 0) {
// must be class + field name
tcls = findClassMapping(context, fieldName.substring
(0, dotIdx), cls, rel);
fieldName = fieldName.substring(dotIdx + 1);
}
if (tcls == null)
throw new MetaDataException(_loc.get(prefix
+ "-bad-fktargetcls", context, fieldName, name));
FieldMapping field = tcls.getFieldMapping(fieldName);
if (field == null)
throw new MetaDataException(_loc.get(prefix
+ "-bad-fktargetfield", new Object[]{ context, fieldName,
name, tcls }));
if (field.getColumns().length != 1)
throw new MetaDataException(_loc.get(prefix
+ "-fktargetfield-cols", context, fieldName, name));
ttable = (field.getJoinForeignKey() != null) ? field.getTable()
: field.getDefiningMapping().getTable();
targetName = field.getColumns()[0].getName();
} else if (targetName != null) {
if (targetName.charAt(0) == '\'') {
constant = true;
target = targetName.substring(1, targetName.length() - 1);
} else if (targetName.charAt(0) == '-'
|| targetName.charAt(0) == '.'
|| Character.isDigit(targetName.charAt(0))) {
constant = true;
try {
if (targetName.indexOf('.') == -1)
target = new Integer(targetName);
else
target = new Double(targetName);
} catch (RuntimeException re) {
throw new MetaDataException(_loc.get(prefix
+ "-bad-fkconst", context, targetName, name));
}
} else if ("null".equalsIgnoreCase(targetName))
constant = true;
else {
int dotIdx = targetName.lastIndexOf('.');
fullTarget = dotIdx != -1;
if (dotIdx == 0) {
// allow use of '.' without prefix to mean "use expected
// local table", but ignore if we're already inversed
if (!inverse)
ttable = local;
targetName = targetName.substring(1);
} else if (dotIdx != -1) {
ttable = findTable(context, targetName.substring(0,
dotIdx), foreign, local, (inverse) ? cls : rel);
targetName = targetName.substring(dotIdx + 1);
}
}
}
// use explicit target table if available
if (ttable == local && local != foreign) {
// swap, unless user gave incompatible table in column name
if (fullName)
throw new MetaDataException(_loc.get(prefix
+ "-bad-fktarget-inverse", new Object[]{ context, name,
foreign, ttable }));
local = foreign;
foreign = ttable;
} else if (ttable != null) {
// ttable might be a table of a base class of the target
foreign = ttable;
}
// check to see if we inversed; if this is a same-table join, then
// consider it an implicit inverse if the user includes the table name
// in the column name, but not in the column target, or if the user
// gives no column name but a full target name
inverse = inverse || local != table || (local == foreign
&& ((fullName && !fullTarget) || (name == null && fullTarget)));
if (!inversable && !constant && inverse) {
if (local == foreign)
throw new MetaDataException(_loc.get(prefix
+ "-bad-fk-self-inverse", context, local));
throw new MetaDataException(_loc.get(prefix + "-bad-fk-inverse",
context, local, table));
}
if (name == null && constant)
throw new MetaDataException(_loc.get(prefix
+ "-no-fkcol-name-adapt", context));
if (name == null && targetName == null) {
// if no name or target is provided and there's more than one likely
// join possibility, too ambiguous
PrimaryKey pk = foreign.getPrimaryKey();
if (joins.length != 1 || pk == null || pk.getColumns().length != 1)
throw new MetaDataException(_loc.get(prefix
+ "-no-fkcol-name-adapt", context));
// assume target is pk column
targetName = pk.getColumns()[0].getName();
} else if (name != null && targetName == null) {
// if one primary key column use it for target; if multiple joins
// look for a foreign column with same name as local column
PrimaryKey pk = foreign.getPrimaryKey();
if (joins.length == 1 && pk != null && pk.getColumns().length == 1)
targetName = pk.getColumns()[0].getName();
else if (foreign.getColumn(name) != null)
targetName = name;
else
throw new MetaDataException(_loc.get(prefix
+ "-no-fkcol-target-adapt", context, name));
}
// find the target column, and create template for local column based
// on it
Column tmplate = new Column();
tmplate.setName(name);
if (!constant) {
Column tcol = foreign.getColumn(targetName);
if (tcol == null)
throw new MetaDataException(_loc.get(prefix + "-bad-fktarget",
new Object[]{ context, targetName, name, foreign }));
if (name == null)
tmplate.setName(tcol.getName());
tmplate.setJavaType(tcol.getJavaType());