All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.enterprisemath.dao.relational.MyBatisRelationDao Maven / Gradle / Ivy

There is a newer version: 4.3.2
Show newest version
package com.enterprisemath.dao.relational;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.enterprisemath.dao.filter.Criterium;
import com.enterprisemath.dao.filter.Filter;
import com.enterprisemath.dao.filter.Order;
import com.enterprisemath.utils.DomainUtils;
import com.enterprisemath.utils.ValidationUtils;

/**
 * Implementation of relation dao which is using my batis framework.
 *
 * @author radek.hecl
 *
 */
public class MyBatisRelationDao implements RelationDao {

    /**
     * Factory for sql sessions.
     */
    private SqlSessionFactory sqlSessionFactory;

    /**
     * Creates new instance.
     */
    private MyBatisRelationDao() {
    }

    /**
     * Guards this object to be consistent. Throws exception if this is not the case.
     */
    private void guardInvariants() {
        ValidationUtils.guardNotNull(sqlSessionFactory, "sqlSessionFactory cannot be null");
    }

    @Override
    public void insertRelation(String code, String subjectCode, String objectCode, String type) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            MyBatisRelationMapper mapper = session.getMapper(MyBatisRelationMapper.class);
            mapper.insertRelation(code, subjectCode, objectCode, type);
        } finally {
            session.close();
        }
    }

    @Override
    public void deleteRelation(String code) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            MyBatisRelationMapper mapper = session.getMapper(MyBatisRelationMapper.class);
            mapper.deleteRelation(code);
        } finally {
            session.close();
        }
    }

    @Override
    public List selectRelations(Set joinsData, Filter filter) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            MyBatisRelationMapper mapper = session.getMapper(MyBatisRelationMapper.class);
            // fetch data
            List> rels = mapper.selectRelations(transformSubjectJoinLabels(joinsData),
                    transformObjectJoinLabels(joinsData), transformFilter(filter));
            if (rels == null || rels.isEmpty()) {
                return Collections.emptyList();
            }
            // map data
            List res = new ArrayList();
            for (Map rel : rels) {
                rel = convertKeysToLowerKeys(rel);
                Relation.Builder builder = new Relation.Builder().
                        setCode((String) rel.get("code")).
                        setType((String) rel.get("type"));

                // build subject
                Entity.Builder subjectBuilder = new Entity.Builder().
                        setCode((String) rel.get("subject_code")).
                        setName((String) rel.get("subject_name")).
                        setType((String) rel.get("subject_type")).
                        setCreatedTimestamp((Date) rel.get("subject_created_timestamp")).
                        setParentCode((String) rel.get("subject_parent_code"));
                for (String label : joinsData) {
                    if (!label.startsWith("subject.")) {
                        continue;
                    }
                    Object obj = rel.get(label.replaceAll("\\.", "_"));
                    if (obj != null && obj instanceof java.sql.Timestamp) {
                        obj = DomainUtils.copyDate((Date) obj);
                    }
                    subjectBuilder.addJoin(label.substring(8), obj);
                }
                builder.setSubject(subjectBuilder.build());

                // build object
                Entity.Builder objectBuilder = new Entity.Builder().
                        setCode((String) rel.get("object_code")).
                        setName((String) rel.get("object_name")).
                        setType((String) rel.get("object_type")).
                        setCreatedTimestamp((Date) rel.get("object_created_timestamp")).
                        setParentCode((String) rel.get("object_parent_code"));
                for (String label : joinsData) {
                    if (!label.startsWith("object.")) {
                        continue;
                    }
                    Object obj = rel.get(label.replaceAll("\\.", "_"));
                    if (obj != null && obj instanceof java.sql.Timestamp) {
                        obj = DomainUtils.copyDate((Date) obj);
                    }
                    objectBuilder.addJoin(label.substring(7), obj);
                }
                builder.setObject(objectBuilder.build());

                res.add(builder.build());
            }

            return res;
        } finally {
            session.close();
        }
    }

    @Override
    public long countRelations(Set joinsData, Set> criteria) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            // extract tables from join data
            Set subjectTables = new HashSet();
            Set objectTables = new HashSet();
            for (String join : joinsData) {
                if (join.startsWith("subject.")) {
                    subjectTables.add(join.substring(8).split("\\.")[0]);
                }
                else if (join.startsWith("object.")) {
                    objectTables.add(join.substring(7).split("\\.")[0]);
                }
                else {
                    throw new RuntimeException("unknown join: join = " + join);
                }
            }
            // transform criteria
            Set> transformedCriteria = new HashSet>();
            for (Criterium crit : criteria) {
                transformedCriteria.add(Criterium.create(transformColumnLabel(crit.getColumn()), crit.getOperator(), crit.getValue()));
            }

            // 
            MyBatisRelationMapper mapper = session.getMapper(MyBatisRelationMapper.class);
            return mapper.countRelations(subjectTables, objectTables, transformedCriteria);
        } finally {
            session.close();
        }
    }

    /**
     * Transform join labels for subject into the table columns format.
     * Key of the map is table name. Values of the set are joins.
     *
     * @param joins join labels to be transformed
     * @return transformed joins
     */
    private Map> transformSubjectJoinLabels(Set joins) {
        Map> res = new HashMap>();
        for (String join : joins) {
            if (!join.startsWith("subject.")) {
                continue;
            }
            String[] parts = join.split("\\.", 3);
            if (!res.containsKey(parts[1])) {
                res.put(parts[1], new HashSet());
            }
            res.get(parts[1]).add(parts[2]);
        }
        return res;
    }

    /**
     * Transform join labels for object into the table columns format.
     * Key of the map is table name. Values of the set are joins.
     *
     * @param joins join labels to be transformed
     * @return transformed joins
     */
    private Map> transformObjectJoinLabels(Set joins) {
        Map> res = new HashMap>();
        for (String join : joins) {
            if (!join.startsWith("object.")) {
                continue;
            }
            String[] parts = join.split("\\.", 3);
            if (!res.containsKey(parts[1])) {
                res.put(parts[1], new HashSet());
            }
            res.get(parts[1]).add(parts[2]);
        }
        return res;
    }

    /**
     * Transforms filter into table columns format.
     *
     * @param filter filter to be transformed
     * @return column filter format
     */
    private Filter transformFilter(Filter filter) {
        Filter.Builder res = new Filter.Builder();
        res.setFrom(filter.getFrom());
        res.setLimit(filter.getLimit());
        for (Criterium crit : filter.getCriteria()) {
            res.addCriterium(Criterium.create(transformColumnLabel(crit.getColumn()), crit.getOperator(), crit.getValue()));
        }
        for (Order ord : filter.getOrders()) {
            res.addOrder(Order.create(transformColumnLabel(ord.getColumn()), ord.getDirection()));
        }
        return res.build();
    }

    /**
     * Transforms column label to the filter format.
     *
     * @param source source label
     * @return output label
     */
    private String transformColumnLabel(String source) {
        if (source.equals("type")) {
            return "r.type";
        }
        else if (source.matches("^subject\\.[^\\.]+")) {
            return "s." + source.substring(8);
        }
        else if (source.matches("^object\\.[^\\.]+")) {
            return "o." + source.substring(7);
        }
        return source.replaceFirst("\\.", "_");
    }

    /**
     * Converts keys in the one map to the lower case.
     *
     * @param source source map
     * @return map with lower case keys
     */
    private Map convertKeysToLowerKeys(Map source) {
        Map res = new HashMap(source.size());
        for (String key : source.keySet()) {
            res.put(key.toLowerCase(), source.get(key));
        }
        return res;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    /**
     * Creates new instance.
     *
     * @param sqlSessionFactory factory for sql sessions
     * @return created instance
     */
    public static MyBatisRelationDao create(SqlSessionFactory sqlSessionFactory) {
        MyBatisRelationDao res = new MyBatisRelationDao();
        res.sqlSessionFactory = sqlSessionFactory;
        res.guardInvariants();
        return res;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy