AgentRepositoryImpl.java

package com.tradecloud.repository.company;

import com.tradecloud.domain.agent.AbstractAgent;
import com.tradecloud.domain.agent.Agent;
import com.tradecloud.domain.agent.AgentSearch;
import com.tradecloud.domain.agent.AgentType;
import com.tradecloud.domain.base.utils.DateUtils;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.domain.party.ServiceProvider;
import com.tradecloud.repository.GeneralRepository;
import com.tradecloud.repository.base.impl.CriteriaOperation;
import com.tradecloud.repository.base.impl.CriteriaValue;
import com.tradecloud.repository.base.impl.RepositoryBaseImpl;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;

@Repository(value = "agentRepository")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class AgentRepositoryImpl extends RepositoryBaseImpl<Agent, AgentSearch> implements AgentRepository {

    private static final long serialVersionUID = 1L;

    private static final Logger log = Logger.getLogger(AgentRepositoryImpl.class);

    @Autowired
    private GeneralRepository generalRepository;

    @Override
    public List<Agent> search(AgentSearch search) {
        if (search.isLiteSearch()) {
            return coreAgentSearchWithStringQuery(search);
        } else {
            DetachedCriteria criteria = DetachedCriteria.forClass(AbstractAgent.class);
            addSearchRestrictions(criteria, search);
            if (search.getSearchMetaParams() != null) {
                if (search.getSearchMetaParams().getOrderBy() == null) {
                    criteria.addOrder(Order.asc("name"));
                }
            } else if (search.getSearchMetaParams() == null) {
                criteria.addOrder(Order.asc("name"));
            }

            return getExecutableCriteriaList(criteria, search.getSearchMetaParams(), "name", true);
        }
    }

    private List<Agent> coreAgentSearchWithStringQuery(AgentSearch search) {
        StringBuilder stringBuilder = new StringBuilder("SELECT * FROM agent ");
        if (search.getAgentType() != null) {
            stringBuilder.append(" LEFT JOIN agent_agenttypes ON agent_agenttypes.agent_id = agent.id ");
            stringBuilder.append(" LEFT JOIN agenttypes ON agent_agenttypes.agenttypes_id = agenttypes.id ");
        }

        if (search.getOrganisationalUnit() != null) {
            stringBuilder.append("LEFT JOIN organisationalunit_agent ON organisationalunit_agent.agent_id = agent.id");
        }

        boolean whereClause = false;

        if (search.getName() != null) {
            stringBuilder.append(whereClause == true ? " AND " : " WHERE ");
            stringBuilder.append("LOWER(agent.name) like '" + LIKE + search.getName().trim().toLowerCase() + LIKE + "'");
            whereClause = true;
        }

        if (search.getExternalReference() != null) {
            stringBuilder.append(whereClause == true ? " AND " : " WHERE ");
            stringBuilder.append("LOWER(agent.externalReference) LIKE '" + LIKE + search.getExternalReference().trim().toLowerCase() + LIKE + "'");
            whereClause = true;
        }

        if (search.getAgentType() != null) {
            String agentType = search.getAgentType().replace(" ", "_");
            agentType = agentType.toUpperCase();
            stringBuilder.append(whereClause == true ? " AND " : " WHERE ");
            stringBuilder.append("agenttypes.typeofagent LIKE '" + LIKE + agentType + LIKE + "'");
            whereClause = true;
        }

        if (search.getCreatedFrom() != null) {
            String date = formatDate(search.getCreatedFrom());
            stringBuilder.append(whereClause == true ? " AND " : " WHERE ");
            stringBuilder.append("agent.created > '" + date + "'");
            whereClause = true;
        }

        if (search.getCreatedTo() != null) {
            String date = formatDate(search.getCreatedTo());
            stringBuilder.append(whereClause == true ? " AND " : " WHERE ");
            stringBuilder.append("agent.created < '" + date + "'");
            whereClause = true;
        }

        if (search.getOrganisationalUnit() != null) {
            OrganisationalUnit organisationalUnit = generalRepository.findByCode(OrganisationalUnit.class, search.getOrganisationalUnit().getCode());

            stringBuilder.append(whereClause == true ? " AND " : " WHERE ");

            String organisationalUnits = "";
            for (OrganisationalUnit organisationalUnit1 : organisationalUnit.getChildren()) {
                organisationalUnits += " '" + organisationalUnit1.getId() + "',";
            }

            if (search.getOrganisationalUnit().getParent() != null) {
                organisationalUnits += " '" + organisationalUnit.getParent().getId() + "',";
            }
            organisationalUnits += " '" + organisationalUnit.getId() + "'";

            stringBuilder.append("organisationalunit_agent.organisationalunit_id IN (" + organisationalUnits + ")");
            whereClause = true;
        }

        if (whereClause) {
            stringBuilder.append(" AND ");
            stringBuilder.append("agent.active = true");
        }
        List<Agent> list = getCurrentSession().createSQLQuery(stringBuilder.toString()).addEntity(Agent.class).list();
        return list;
    }

    private String formatDate(Date date) {
        SimpleDateFormat parseFormat =
                new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
        Date oldDate = null;
        String result = "";
        try {
            oldDate = parseFormat.parse(date.toString());
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            result = format.format(oldDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public long countByCriteria(AgentSearch search) {
        // hack!
        long total = 0l;
        total += countAgent(search, Agent.class);
        return total;
    }

    private long countAgent(AgentSearch search, Class clazz) {
        DetachedCriteria criteria = DetachedCriteria.forClass(clazz);
        addSearchRestrictions(criteria, search);

        long count = getExecutableCriteriaCount(criteria);
        log.debug("Count for Class=" + clazz.getSimpleName() + " is " + count);
        return count;
    }

    private void addSearchRestrictions(DetachedCriteria criteria, AgentSearch search) {

        log.debug("addSearchRestrictions " + search.toString());

        if (search.getName() != null) {
            // criteria.add(Restrictions.like("name", LIKE + search.getName() + LIKE));
            criteria.add(Restrictions.ilike("name", search.getName(), MatchMode.ANYWHERE));
        }

        if (search.getExternalReference() != null) {
            criteria.add(Restrictions.like("externalReference", LIKE + search.getExternalReference() + LIKE));
        }

        if (search.getCreatedFrom() != null) {
            criteria.add(Restrictions.ge("created", DateUtils.getStartOfDay(search.getCreatedFrom())));
        }

        if (search.getCreatedTo() != null) {
            criteria.add(Restrictions.le("created", DateUtils.getEndOfDay(search.getCreatedTo())));
        }

        if (search.getCountry() != null) {
            DetachedCriteria eventCrit = criteria.createCriteria("physicalAddress").add(Restrictions.eq("country", search.getCountry()));
            eventCrit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        }

        if (search.getCurrency() != null) {
            criteria.add(Restrictions.eq("currency", search.getCurrency()));
        }

        if (search.getAgentType() != null) {
            criteria.createAlias("agentTypes", "at");
            criteria.add(Restrictions.eq("at.typeofAgent", AgentType.get(search.getAgentType())));
        }
    }

    /**
     * A convenience method that maps each search field from {@code ProductSearch} to the corresponding value from the search.
     *
     * @param search The {@code ProductSearch} whose names and values will create the map
     * @return A map of search field-name to field-value
     */
    @Override
    protected Collection<CriteriaValue> mapFieldsToValues(AgentSearch search) {
        log.debug("mapFieldsToValues " + search.toString());
        Collection<CriteriaValue> fields = new LinkedHashSet<CriteriaValue>();
        fields.add(new CriteriaValue(CriteriaOperation.EQUALS, "name", search.getName()));
        fields.add(new CriteriaValue(CriteriaOperation.EQUALS, "externalReference", search.getExternalReference()));
        // fields.add(new CriteriaValue(CriteriaOperation.EQUALS, "state", search.getState()));
        fields.add(new CriteriaValue(CriteriaOperation.EQUALS, "currency", search.getCurrency()));
        fields.add(new CriteriaValue(CriteriaOperation.GREATER_THAN, "created", search.getCreatedFrom()));
        fields.add(new CriteriaValue(CriteriaOperation.LESS_THAN, "created", search.getCreatedTo()));
        /*
         * if (search.getActive() != null) { fields.add(new CriteriaValue(CriteriaOperation.EQUALS, "active",
         * search.getActive().equals(ActiveType.ACTIVE))); }
         */
        return fields;
    }

    @Override
    public List<Agent> findAgents() {
        return (List<Agent>) loadAll(Agent.class);
    }

    @Override
    public List<Agent> findActiveAgents() {
        return (List<Agent>) find("from Agent where active=true");
    }

    @Override
    public List<Agent> findByServiceProvider(ServiceProvider serviceProvider) {
        return getCurrentSession().createQuery("from Agent where serviceProvider=:sp").setParameter("sp", serviceProvider).list();
    }
}