org.openehealth.ipf.commons.flow.repository.FlowRepositoryImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.openehealth.ipf.commons.flow.repository.FlowRepositoryImpl.java

Source

/*
 * Copyright 2008 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.openehealth.ipf.commons.flow.repository;

import static org.hibernate.criterion.Restrictions.*;

import java.util.Collection;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.openehealth.ipf.commons.flow.FlowException;
import org.openehealth.ipf.commons.flow.domain.Flow;
import org.openehealth.ipf.commons.flow.domain.FlowStatus;
import org.openehealth.ipf.commons.flow.repository.FlowPurgeCriteria.PurgeMode;
import org.openehealth.ipf.commons.flow.repository.search.DefaultSearchCallback;
import org.openehealth.ipf.commons.flow.repository.search.FlowSearchCallback;
import org.openehealth.ipf.commons.flow.repository.search.FlowSearchCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * @author Martin Krasser
 * @author Mitko Kolev 
 */
public class FlowRepositoryImpl extends HibernateDaoSupport implements FlowRepository {

    private static final Log LOG = LogFactory.getLog(FlowRepositoryImpl.class);

    @Autowired(required = false)
    private SequenceRepository sequenceRepository;

    @Autowired(required = false)
    private final FlowSearchCallback flowSearchCallback;

    public FlowRepositoryImpl() {
        flowSearchCallback = new DefaultSearchCallback();
    }

    @Override
    public void initDao() throws Exception {
        super.initDao();
        if (sequenceRepository == null) {
            sequenceRepository = new SequenceRepositoryMock();
            LOG.warn("no sequence repository injected, using mock repository");
        }
        sequenceRepository.initSequence();
    }

    @Override
    public void persist(Flow flow) {
        // Generate a sequence number for flow
        flow.setIdentifier(sequenceRepository.nextNumber());
        // Persist flow using the assigned number
        getHibernateTemplate().persist(flow);
    }

    @Override
    public void merge(Flow flow) {
        getHibernateTemplate().merge(flow);
    }

    @Override
    public void remove(Flow flow) {
        getHibernateTemplate().delete(flow);
    }

    void removeAll(Collection<Flow> flows) {
        getHibernateTemplate().deleteAll(flows);
    }

    @Override
    public Flow find(Long id) {
        Flow flow = (Flow) getHibernateTemplate().get(Flow.class, id);
        if (flow == null) {
            throw new FlowException("no flow with id " + id);
        }
        return flow;
    }

    @Override
    public Flow lock(Long id) {
        try {
            return (Flow) getHibernateTemplate().load(Flow.class, id, LockMode.UPGRADE);
        } catch (HibernateObjectRetrievalFailureException e) {
            throw new FlowException("no flow with id " + id);
        }
    }

    @Override
    public int purgeFlows(FlowPurgeCriteria purgeCriteria) {
        List<Flow> purgeCandidates = findPurgeCandidates(purgeCriteria);
        getHibernateTemplate().deleteAll(findPurgeCandidates(purgeCriteria));
        getHibernateTemplate().flush();
        return purgeCandidates.size();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Flow> findFlows(final FlowFinderCriteria finderCriteria) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                return execute(finderCriteria, createFlowsCriteria(finderCriteria), session, false);
            }
        });
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Flow> findErrorFlows(final FlowFinderCriteria finderCriteria) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                return execute(finderCriteria, createErrorFlowsCriteria(finderCriteria), session, false);
            }
        });
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Flow> findUnackFlows(final FlowFinderCriteria finderCriteria) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                return execute(finderCriteria, createUnackFlowsCriteria(finderCriteria), session, false);
            }
        });
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Long> findFlowIds(final FlowFinderCriteria finderCriteria) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                return execute(finderCriteria, createFlowsCriteria(finderCriteria), session, true);
            }
        });
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Long> findErrorFlowIds(final FlowFinderCriteria finderCriteria) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                return execute(finderCriteria, createErrorFlowsCriteria(finderCriteria), session, true);
            }
        });
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Long> findUnackFlowIds(final FlowFinderCriteria finderCriteria) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                return execute(finderCriteria, createUnackFlowsCriteria(finderCriteria), session, true);
            }
        });
    }

    @SuppressWarnings("unchecked")
    private List<Flow> findPurgeCandidates(final FlowPurgeCriteria purgeCriteria) {
        return getHibernateTemplate().executeFind(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session) throws HibernateException {
                return execute(purgeCriteria, createPurgeCriteria(purgeCriteria), session);
            }
        });
    }

    private Object execute(FlowFinderCriteria flowFinderCriteria, DetachedCriteria flowStatusCriteria,
            Session session, boolean idProjection) {

        Criteria criteria = flowStatusCriteria.getExecutableCriteria(session);

        if (idProjection) {
            criteria.setProjection(Projections.id());
        }

        int maxResults = flowFinderCriteria.getMaxResults();
        if (maxResults != FlowFinderCriteria.DEFAULT_MAX_RESULTS) {
            criteria.setMaxResults(maxResults);
        }

        if (flowFinderCriteria.hasMessageQuery()) {
            FlowSearchCriteria flowSearchCriteria = new FlowSearchCriteria();
            flowSearchCriteria.setHibernateCriteria(criteria);
            flowSearchCriteria.setInboundMessageQuery(flowFinderCriteria.getInboundMessageQuery());
            flowSearchCriteria.setOutboundMessageQuery(flowFinderCriteria.getOutboundMessageQuery());
            return flowSearchCallback.findFlows(session, flowSearchCriteria);
        } else {
            return criteria.list();
        }
    }

    private Object execute(FlowPurgeCriteria flowPurgeCriteria, DetachedCriteria flowStatusCriteria,
            Session session) {
        Criteria criteria = flowStatusCriteria.getExecutableCriteria(session);

        int purgeCount = flowPurgeCriteria.getMaxPurgeCount();
        if (purgeCount != FlowPurgeCriteria.DEFAULT_MAX_PURGE_COUNT) {
            // Setting max results adds "fetch first 100 rows only" to the select query
            // Works on Derby version 1.5.x and above with Hibernate version 3.5.x and above
            criteria.setMaxResults(purgeCount);
        }
        return criteria.list();
    }

    private static DetachedCriteria createFlowsCriteria(FlowFinderCriteria finderCriteria) {
        DetachedCriteria criteria = DetachedCriteria.forClass(Flow.class)
                .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).setFetchMode("parts", FetchMode.JOIN) // eager
                .add(ge("creationTime", finderCriteria.getFrom())).addOrder(Order.desc("identifier"));

        if (finderCriteria.getApplication() != null) {
            // constrain query to a certain application name
            criteria.add(eq("application", finderCriteria.getApplication()));
        }
        if (finderCriteria.getTo() != null) {
            // there's an upper limit to creationTime property
            criteria.add(Restrictions.le("creationTime", finderCriteria.getTo()));
        }

        return criteria;
    }

    private static DetachedCriteria createErrorFlowsCriteria(FlowFinderCriteria finderCriteria) {
        return createFlowsCriteria(finderCriteria).createAlias("parts", "p").add(eq("p.status", FlowStatus.ERROR));
    }

    private static DetachedCriteria createUnackFlowsCriteria(FlowFinderCriteria finderCriteria) {
        return createFlowsCriteria(finderCriteria).add(isEmpty("parts"));
    }

    private static DetachedCriteria createPurgeCriteria(FlowPurgeCriteria purgeCriteria) {
        DetachedCriteria criteria = DetachedCriteria.forClass(Flow.class)
                .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                // purge all flows with a creation time older than time limit
                .add(lt("creationTime", purgeCriteria.getTimeLimit()))
                // purge oldest flows first
                .addOrder(Order.asc("creationTime"));

        if (purgeCriteria.getApplication() != null) {
            criteria.add(eq("application", purgeCriteria.getApplication()));
        }

        if (purgeCriteria.getPurgeMode() == PurgeMode.CLEAN) {
            // omit flows with error status
            criteria.add(or(eq("derivedStatus", FlowStatus.CLEAN), isNull("derivedStatus") // old flows (both CLEAN and ERROR)
            ));

        }
        return criteria;
    }

}