Package org.nutz.dao.impl.entity

Source Code of org.nutz.dao.impl.entity.NutEntity

package org.nutz.dao.impl.entity;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.nutz.dao.DaoException;
import org.nutz.dao.FieldMatcher;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.EntityIndex;
import org.nutz.dao.entity.LinkField;
import org.nutz.dao.entity.LinkVisitor;
import org.nutz.dao.entity.MappingField;
import org.nutz.dao.entity.PkType;
import org.nutz.dao.entity.Record;
import org.nutz.dao.sql.Pojo;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.born.BornContext;
import org.nutz.lang.born.Borning;
import org.nutz.lang.born.Borns;
import org.nutz.lang.util.Context;

/**
* 记录一个实体
*
* @author zozoh(zozohtnt@gmail.com)
*/
public class NutEntity<T> implements Entity<T> {

    /**
     * 按照 Java 字段名索引映射字段
     */
    private Map<String, MappingField> byJava;

    /**
     * 按照数据库字段名索引映射字段
     */
    private Map<String, MappingField> byDB;

    /**
     * 按照增加顺序,记录所有映射字段
     */
    private List<MappingField> fields;

    /**
     * 按照顺序存储实体所有的索引
     */
    private List<EntityIndex> indexes;

    /**
     * 实体索引按照名称方式的散列
     */
    private Map<String, EntityIndex> indexMap;

    /**
     * 按顺序记录复合主键
     */
    private List<MappingField> theComposites;

    /**
     * 预执行宏列表
     */
    private List<Pojo> beforeInsertMacroes;

    /**
     * 后执行字段宏列表
     */
    private List<Pojo> afterInsertMacroes;

    /**
     * 所有一对一映射字段
     */
    protected LinkFieldSet ones;

    /**
     * 所有一对多映射字段
     */
    protected LinkFieldSet manys;

    /**
     * 所有多对多映射字段
     */
    protected LinkFieldSet manymanys;

    /**
     * 数字型主键
     */
    private MappingField theId;

    /**
     * 字符型主键
     */
    private MappingField theName;

    /**
     * 实体 Java 类型
     */
    protected Class<T> type;

    /**
     * 实体 Java 类型:通过 Mirror 增强
     */
    private Mirror<T> mirror;

    /**
     * 根据 ResultSet 创建实体的方法
     */
    protected Borning<T> bornByRS;

    /**
     * 根据默认构造函数或者工厂方法创建实体的方法
     */
    protected Borning<T> bornByDefault;

    /**
     * 实体表名
     */
    private EntityName tableName;

    /**
     * 实体表注释
     */
    private String tableComment;

    /**
     * 字段注释
     */
    private Map<String, String> columnComments;

    /**
     * 是否有表注释
     */
    private boolean hasTableComment;

    /**
     * 是否有字段注释
     */
    private boolean hasColumnComment;

    /**
     * 实体视图名
     */
    private EntityName viewName;

    /**
     * 实体补充描述
     */
    private Map<String, Object> metas;

    /**
     * 实体的主键类型
     */
    private PkType pkType;

    public NutEntity(Class<T> type) {
        this.type = type;
        this.mirror = Mirror.me(type);
        this.byJava = new HashMap<String, MappingField>();
        this.byDB = new HashMap<String, MappingField>();
        this.indexMap = new HashMap<String, EntityIndex>();
        this.fields = new ArrayList<MappingField>(5);
        this.indexes = new ArrayList<EntityIndex>(3);
        this.theComposites = new ArrayList<MappingField>(3);
        this.metas = new HashMap<String, Object>();
        this.columnComments = new HashMap<String, String>();

        this.pkType = PkType.UNKNOWN;

        // 字段宏
        beforeInsertMacroes = new ArrayList<Pojo>(3);
        afterInsertMacroes = new ArrayList<Pojo>(3);

        // 获得默认的构造方法
        try {
            bornByDefault = mirror.getBorningByArgTypes();
        }
        catch (Exception e) {}

        // 检查对象的创建方法
        BornContext<T> bc = Borns.evalByArgTypes(type, ResultSet.class);
        if (null != bc)
            this.bornByRS = bc.getBorning();
        else if (null == bornByDefault)
          throw new DaoException("Need non-arg constructor : " + type);

        // 映射
        this.ones = new LinkFieldSet();
        this.manys = new LinkFieldSet();
        this.manymanys = new LinkFieldSet();
    }

    public T getObject(ResultSet rs, FieldMatcher matcher) {
        // 构造时创建对象
        if (null != bornByRS)
            return bornByRS.born(Lang.array(rs));

        // 通过反射每个字段逐次设置对象
        T re = bornByDefault.born(new Object[]{});
        if (null == matcher)
            for (MappingField fld : fields)
                fld.injectValue(re, rs);
        else
            for (MappingField fld : fields)
                if (matcher.match(fld.getName()))
                    fld.injectValue(re, rs);

        // 返回构造的对象
        return re;
    }

    public T getObject(Record rec) {
        T obj = bornByDefault.born(new Object[]{});
        for (MappingField fld : fields)
            fld.injectValue(obj, rec);
        return obj;

    }

    /**
     * 当所有字段增加完成,这个方法必须被调用,用来搜索复合主键
     *
     * @param names
     *            复合主键的 Java 字段名数组
     */
    public void checkCompositeFields(String[] names) {
        if (!Lang.isEmptyArray(names) && names.length > 1) {
            for (String name : names) {
                if (byJava.containsKey(name) && byJava.get(name).isCompositePk())
                    theComposites.add(byJava.get(name));
                else
                    throw Lang.makeThrow(    "Fail to find comosite field '%s' in class '%s'!",
                                            name,
                                            type.getName());
            }
            this.pkType = PkType.COMPOSITE;
        } else if (null != this.theId) {
            this.pkType = PkType.ID;
        } else if (null != this.theName) {
            this.pkType = PkType.NAME;
        }
    }

    /**
     * 增加映射字段
     *
     * @param field
     *            数据库实体字段
     */
    public void addMappingField(MappingField field) {
        if (field.isId())
            theId = field;
        else if (field.isName())
            theName = field;
        byJava.put(field.getName(), field);
        byDB.put(field.getColumnName(), field);
        fields.add(field);
        columnComments.put(field.getName(), field.getColumnComment());
    }

    /**
     *
     * @param lnk
     */
    public void addLinkField(LinkField lnk) {
        switch (lnk.getLinkType()) {
        case ONE:
            ones.add(lnk);
            break;
        case MANY:
            manys.add(lnk);
            break;
        case MANYMANY:
            manymanys.add(lnk);
            break;
        default:
            throw Lang.makeThrow(    "It is a miracle in Link field: '%s'(%s)",
                                    lnk.getName(),
                                    lnk.getEntity().getType().getName());
        }
    }

    /**
     * 增加实体索引
     *
     * @param index
     *            实体索引
     */
    public void addIndex(EntityIndex index) {
        indexes.add(index);
        indexMap.put(index.getName(), index);
    }

    public Context wrapAsContext(Object obj) {
        return new EntityObjectContext(this, obj);
    }

    public List<LinkField> visitOne(Object obj, String regex, LinkVisitor visitor) {
        return ones.visit(obj, regex, visitor);
    }

    public List<LinkField> visitMany(Object obj, String regex, LinkVisitor visitor) {
        return manys.visit(obj, regex, visitor);
    }

    public List<LinkField> visitManyMany(Object obj, String regex, LinkVisitor visitor) {
        return manymanys.visit(obj, regex, visitor);
    }

    public void setTableName(String namep) {
        this.tableName = EntityName.create(namep);
    }

    public void setTableComment(String tComment) {
        this.tableComment = tComment;
    }

    public void setHasTableComment(boolean hasTableComment) {
        this.hasTableComment = hasTableComment;
    }

    public void setHasColumnComment(boolean hasColumnComment) {
        this.hasColumnComment = hasColumnComment;
    }

    public void setBeforeInsertMacroes(List<Pojo> beforeInsertMacroes) {
        this.beforeInsertMacroes = beforeInsertMacroes;
    }

    public void setAfterInsertMacroes(List<Pojo> afterInsertMacroes) {
        this.afterInsertMacroes = afterInsertMacroes;
    }

    public void setViewName(String namep) {
        this.viewName = EntityName.create(namep);
    }

    public MappingField getField(String name) {
        return byJava.get(name);
    }

    public MappingField getColumn(String name) {
        return byDB.get(name);
    }

    public List<MappingField> getMappingFields() {
        return fields;
    }

    public List<LinkField> getLinkFields(String regex) {
        List<LinkField> reOnes = ones.getList(regex);
        List<LinkField> reManys = manys.getList(regex);
        List<LinkField> reManymanys = manymanys.getList(regex);
        List<LinkField> re = new ArrayList<LinkField>(reOnes.size()
                                                        + reManys.size()
                                                        + reManymanys.size());
        re.addAll(reOnes);
        re.addAll(reManys);
        re.addAll(reManymanys);
        return re;
    }

    public List<MappingField> getCompositePKFields() {
        return this.theComposites;
    }

    public MappingField getNameField() {
        return this.theName;
    }

    public MappingField getIdField() {
        return this.theId;
    }

    public List<MappingField> getPks() {
        if (null != theId)
            return Lang.list(theId);
        if (null != theName)
            return Lang.list(theName);
        return theComposites;
    }

    public Class<T> getType() {
        return this.type;
    }

    public Mirror<T> getMirror() {
        return this.mirror;
    }

    public List<EntityIndex> getIndexes() {
        return this.indexes;
    }

    public EntityIndex getIndex(String name) {
        return this.indexMap.get(name);
    }

    public String getTableName() {
        return this.tableName.value();
    }

    public String getViewName() {
        return this.viewName.value();
    }

    public boolean addBeforeInsertMacro(Pojo pojo) {
        if (null != pojo) {
            beforeInsertMacroes.add(pojo);
            return true;
        }
        return false;
    }

    public boolean addAfterInsertMacro(Pojo pojo) {
        if (null != pojo) {
            afterInsertMacroes.add(pojo);
            return true;
        }
        return false;
    }

    public List<Pojo> cloneBeforeInsertMacroes() {
        List<Pojo> re = new ArrayList<Pojo>(beforeInsertMacroes.size());
        for (Pojo pojo : beforeInsertMacroes)
            re.add(pojo.duplicate());
        return re;
    }

    public List<Pojo> cloneAfterInsertMacroes() {
        List<Pojo> re = new ArrayList<Pojo>(afterInsertMacroes.size());
        for (Pojo pojo : afterInsertMacroes)
            re.add(pojo.duplicate());
        return re;
    }

    public PkType getPkType() {
        return pkType;
    }

    public Object getMeta(String key) {
        return metas.get(key);
    }

    public boolean hasMeta(String key) {
        return metas.containsKey(key);
    }

    public Map<String, Object> getMetas() {
        return metas;
    }

    public String toString() {
        return String.format("Entity<%s:%s>", getType().getName(), getTableName());
    }

    public boolean hasTableComment() {
        return hasTableComment;
    }

    public String getTableComment() {
        return tableComment;
    }

    public boolean hasColumnComment() {
        return hasColumnComment;
    }

    public String getColumnComent(String columnName) {
        return columnComments.get(columnName);
    }
}
TOP

Related Classes of org.nutz.dao.impl.entity.NutEntity

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.