package jef.database.meta;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jef.database.IQueryableEntity;
import jef.database.annotation.DynamicTable;
import jef.database.dialect.type.ColumnMapping;
import jef.database.meta.AnnotationProvider.ClassAnnotationProvider;
import jef.database.query.ConditionQuery;
import jef.tools.reflect.BeanUtils;
import jef.tools.reflect.FieldAccessor;
import jef.tools.reflect.FieldEx;
public class ExtensionTemplate implements ExtensionConfigFactory {
private final Map<String, ExtensionInstance> cache = new ConcurrentHashMap<String, ExtensionInstance>();
@SuppressWarnings("unused")
private DynamicTable dt;
private FieldAccessor keyAccessor;
private AbstractMetadata parent;
List<java.lang.reflect.Field> unprocessedField;
ClassAnnotationProvider annos;
public ExtensionTemplate(DynamicTable dt, Class<?> clz, AbstractMetadata meta) {
this.dt = dt;
this.parent = meta;
String keyField = dt.resourceTypeField();
FieldEx field = BeanUtils.getField(clz, keyField);
if (field == null) {
throw new IllegalArgumentException("Field " + keyField + " not exist");
}
this.keyAccessor = field.getAccessor();
}
public AbstractMetadata getTemplate() {
return parent;
}
public FieldAccessor getKeyAccessor() {
return keyAccessor;
}
@Override
public ExtensionConfig getExtension(IQueryableEntity q) {
if (q == null) {
throw new IllegalArgumentException();
}
String key = (String) keyAccessor.getObject(q);
if (key == null || key.length() == 0) {
if (q.hasQuery()) {
key = (String) q.getQuery().getAttribute(ConditionQuery.CUSTOM_TABLE_TYPE);
}
if (key == null || key.length() == 0)
throw new IllegalArgumentException("the entity has no key for dynamic extendsion");
}
return getExtension(key);
}
@Override
public ExtensionConfig getExtension(String extensionName) {
ExtensionInstance ec = cache.get(extensionName);
if (ec != null)
return ec;
ec = new ExtensionInstance(extensionName, parent);
cache.put(extensionName, ec);
return ec;
}
@Override
public ExtensionConfig getDefault() {
// throw new UnsupportedOperationException();
return null;
}
final class ExtensionInstance extends AbstractExtensionConfig {
public ExtensionInstance(String key, AbstractMetadata meta) {
super(key, meta);
}
@Override
public boolean isDynamicTable() {
return true;
}
@Override
protected DynamicMetadata merge() {
DynamicMetadata tuple = new DynamicMetadata(parent, this);
for (ColumnMapping f : getExtensionMeta().getColumns()) {
tuple.updateColumn(f.fieldName(), f.rawColumnName(), f.get(), f.isPk());
}
// 针对未处理的字段,当做外部引用关系处理
for (java.lang.reflect.Field f : unprocessedField) {
// 将这个字段作为外部引用处理
MetaHolder.processReference(tuple, annos.forField(f));
// 还有一种情况,即定义了Column注解,但不属于元模型的一个字段,用于辅助映射的。当结果拼装时有用
// processColumnHelper(f, tuple, annos);
}
return tuple;
}
}
}