package org.nutz.dao.impl.entity.field;
import org.nutz.dao.Cnd;
import org.nutz.dao.Condition;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.LinkField;
import org.nutz.dao.entity.LinkType;
import org.nutz.dao.entity.PkType;
import org.nutz.dao.impl.EntityHolder;
import org.nutz.dao.impl.entity.EntityName;
import org.nutz.dao.impl.entity.info.LinkInfo;
import org.nutz.dao.util.cri.SimpleCriteria;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
public class ManyManyLinkField extends AbstractLinkField implements LinkField {
private EntityName relationTableName;
private String fromColumnName;
private String toColumnName;
public ManyManyLinkField(Entity<?> host, EntityHolder holder, LinkInfo info) {
super(host, holder, info);
this.targetType = info.manymany.target();
this.mapKey = info.manymany.key();
this.relationTableName = EntityName.create(info.manymany.relation());
String[] ss = Strings.splitIgnoreBlank(info.manymany.from(), ":");
this.fromColumnName = ss[0];
String fromField = ss.length > 1 ? ss[1] : null;
ss = Strings.splitIgnoreBlank(info.manymany.to(), ":");
this.toColumnName = ss[0];
String toField = ss.length > 1 ? ss[1] : null;
/*
* 开始分析两个实体的链接字段
*/
Entity<?> ta = this.getLinkedEntity();
// 用户指定了 "from" 的 Java 字段名
if (fromField != null) {
hostField = host.getField(fromField);
}
// 用户指定了 "to" 的 Java 字段名
if (null != toField) {
linkedField = ta.getField(toField);
}
// 用户仅仅指定了 "from" 的 Java 字段
if (null != hostField && linkedField == null) {
linkedField = ta.getPkType() == PkType.ID ? ta.getIdField() : ta.getNameField();
}
// 用户仅仅指定了 "to" 的 Java 字段
else if (null == hostField && linkedField != null) {
hostField = host.getPkType() == PkType.ID ? host.getIdField() : host.getNameField();
}
// 都没指定,优先使用 Id 的链接主键
else {
// 都有 ID
if (null != host.getIdField() && null != ta.getIdField()) {
hostField = host.getIdField();
linkedField = ta.getIdField();
}
// 宿主ID,链 Name
else if (null != host.getIdField() && null != ta.getNameField()) {
hostField = host.getIdField();
linkedField = ta.getNameField();
}
// 宿主Name 链 ID
else if (null != host.getNameField() && null != ta.getIdField()) {
hostField = host.getNameField();
linkedField = ta.getIdField();
}
// 都有 Name
else if (null != host.getNameField() && null != ta.getNameField()) {
hostField = host.getNameField();
linkedField = ta.getNameField();
}
}
// 最后再检查一下 ...
if (null == hostField || null == linkedField) {
throw Lang.makeThrow( "Invalid @ManyMany in '%s'(%s): lack @Id or @Name",
info.name,
host.getType().getName());
}
}
public Condition createCondition(Object host) {
SimpleCriteria cri = Cnd.cri();
cri.where().andInBySql( linkedField.getColumnName(),
"SELECT %s FROM %s WHERE %s=%s",
toColumnName,
this.getRelationName(),
fromColumnName,
Sqls.formatFieldValue(hostField.getValue(host)));
return cri;
}
public void updateLinkedField(Object obj, Object linked) {}
public void saveLinkedField(Object obj, Object linked) {}
public LinkType getLinkType() {
return LinkType.MANYMANY;
}
public String getRelationName() {
return this.relationTableName.value();
}
public String getFromColumnName() {
return fromColumnName;
}
public String getToColumnName() {
return toColumnName;
}
/**
* 返回关联两个实体的主键 Java 字段名数组
* <p>
* 数组的第一个元素是宿主主键的字段名,第二个元素是映射实体的主键字段名
*
* @return 关联两个实体的主键 Java 字段名数组
*/
public String[] getLinkedPkNames() {
String[] re = new String[2];
re[0] = hostField.getName();
re[1] = linkedField.getName();
return re;
}
}