Fix return type
authorPatrick Plitzner <p.plitzner@bgbm.org>
Tue, 3 Nov 2015 10:07:35 +0000 (11:07 +0100)
committerPatrick Plitzner <p.plitzner@bgbm.org>
Tue, 3 Nov 2015 10:07:35 +0000 (11:07 +0100)
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/occurrence/OccurrenceDaoHibernateImpl.java
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/occurrence/IOccurrenceDao.java

index 77818bd372c63db6269ed7b23090c1757ab6d20b..9d56395887467d6fbed1b34b275da86fe8fd6d34 100644 (file)
-/**\r
-* Copyright (C) 2008 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*/\r
-\r
-package eu.etaxonomy.cdm.persistence.dao.hibernate.occurrence;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.UUID;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.hibernate.Criteria;\r
-import org.hibernate.Hibernate;\r
-import org.hibernate.Query;\r
-import org.hibernate.Session;\r
-import org.hibernate.criterion.Projections;\r
-import org.hibernate.criterion.Restrictions;\r
-import org.hibernate.envers.query.AuditEntity;\r
-import org.hibernate.envers.query.AuditQuery;\r
-import org.hibernate.search.FullTextSession;\r
-import org.hibernate.search.Search;\r
-import org.springframework.beans.factory.annotation.Autowired;\r
-import org.springframework.stereotype.Repository;\r
-\r
-import eu.etaxonomy.cdm.model.description.DescriptionBase;\r
-import eu.etaxonomy.cdm.model.description.IndividualsAssociation;\r
-import eu.etaxonomy.cdm.model.media.Media;\r
-import eu.etaxonomy.cdm.model.molecular.DnaSample;\r
-import eu.etaxonomy.cdm.model.name.HomotypicalGroup;\r
-import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;\r
-import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;\r
-import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
-import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
-import eu.etaxonomy.cdm.model.occurrence.FieldUnit;\r
-import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;\r
-import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;\r
-import eu.etaxonomy.cdm.model.taxon.Taxon;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
-import eu.etaxonomy.cdm.model.view.AuditEvent;\r
-import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;\r
-import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;\r
-import eu.etaxonomy.cdm.persistence.dao.hibernate.taxon.TaxonDaoHibernateImpl;\r
-import eu.etaxonomy.cdm.persistence.dao.name.IHomotypicalGroupDao;\r
-import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;\r
-import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;\r
-import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;\r
-import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
-import eu.etaxonomy.cdm.persistence.query.OrderHint;\r
-\r
-/**\r
- * @author a.babadshanjan\r
- * @created 01.09.2008\r
- */\r
-@Repository\r
-public class OccurrenceDaoHibernateImpl extends IdentifiableDaoBase<SpecimenOrObservationBase> implements IOccurrenceDao {\r
-\r
-    @SuppressWarnings("unused")\r
-    private static final Logger logger = Logger.getLogger(TaxonDaoHibernateImpl.class);\r
-\r
-    @Autowired\r
-    private IDescriptionDao descriptionDao;\r
-\r
-    @Autowired\r
-    private ITaxonNameDao taxonNameDao;\r
-\r
-    @Autowired\r
-    private IHomotypicalGroupDao homotypicalGroupDao;\r
-\r
-    public OccurrenceDaoHibernateImpl() {\r
-        super(SpecimenOrObservationBase.class);\r
-        indexedClasses = new Class[7];\r
-        indexedClasses[0] = FieldUnit.class;\r
-        indexedClasses[1] = DerivedUnit.class;\r
-        indexedClasses[5] = DnaSample.class;\r
-    }\r
-\r
-    @Override\r
-    public int countDerivationEvents(SpecimenOrObservationBase occurence) {\r
-        checkNotInPriorView("OccurrenceDaoHibernateImpl.countDerivationEvents(SpecimenOrObservationBase occurence)");\r
-        Query query = getSession().createQuery("select count(distinct derivationEvent) from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");\r
-        query.setParameter("occurence", occurence);\r
-\r
-        return ((Long)query.uniqueResult()).intValue();\r
-    }\r
-\r
-    @Override\r
-    public int countDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase) {\r
-        AuditEvent auditEvent = getAuditEventFromContext();\r
-        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {\r
-            Criteria criteria = getSession().createCriteria(DeterminationEvent.class);\r
-            if(occurrence != null) {\r
-                criteria.add(Restrictions.eq("identifiedUnit",occurrence));\r
-            }\r
-\r
-            if(taxonBase != null) {\r
-                criteria.add(Restrictions.eq("taxon",taxonBase));\r
-            }\r
-\r
-            criteria.setProjection(Projections.rowCount());\r
-            return ((Number)criteria.uniqueResult()).intValue();\r
-        } else {\r
-            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(DeterminationEvent.class,auditEvent.getRevisionNumber());\r
-\r
-            if(occurrence != null) {\r
-                query.add(AuditEntity.relatedId("identifiedUnit").eq(occurrence.getId()));\r
-            }\r
-\r
-            if(taxonBase != null) {\r
-                query.add(AuditEntity.relatedId("taxon").eq(taxonBase.getId()));\r
-            }\r
-            query.addProjection(AuditEntity.id().count("id"));\r
-\r
-            return ((Long)query.getSingleResult()).intValue();\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public int countMedia(SpecimenOrObservationBase occurence) {\r
-        checkNotInPriorView("OccurrenceDaoHibernateImpl.countMedia(SpecimenOrObservationBase occurence)");\r
-        Query query = getSession().createQuery("select count(media) from SpecimenOrObservationBase occurence join occurence.media media where occurence = :occurence");\r
-        query.setParameter("occurence", occurence);\r
-\r
-        return ((Long)query.uniqueResult()).intValue();\r
-    }\r
-\r
-    @Override\r
-    public List<DerivationEvent> getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber, List<String> propertyPaths) {\r
-        checkNotInPriorView("OccurrenceDaoHibernateImpl.getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber)");\r
-        Query query = getSession().createQuery("select distinct derivationEvent from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");\r
-        query.setParameter("occurence", occurence);\r
-\r
-        if(pageSize != null) {\r
-            query.setMaxResults(pageSize);\r
-            if(pageNumber != null) {\r
-                query.setFirstResult(pageNumber * pageSize);\r
-            } else {\r
-                query.setFirstResult(0);\r
-            }\r
-        }\r
-\r
-        List<DerivationEvent> result = query.list();\r
-        defaultBeanInitializer.initializeAll(result, propertyPaths);\r
-        return result;\r
-    }\r
-\r
-    @Override\r
-    public List<DeterminationEvent> getDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {\r
-        AuditEvent auditEvent = getAuditEventFromContext();\r
-        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {\r
-            Criteria criteria = getSession().createCriteria(DeterminationEvent.class);\r
-            if(occurrence != null) {\r
-                criteria.add(Restrictions.eq("identifiedUnit",occurrence));\r
-            }\r
-\r
-            if(taxonBase != null) {\r
-                criteria.add(Restrictions.eq("taxon",taxonBase));\r
-            }\r
-\r
-            if(pageSize != null) {\r
-                criteria.setMaxResults(pageSize);\r
-                if(pageNumber != null) {\r
-                    criteria.setFirstResult(pageNumber * pageSize);\r
-                } else {\r
-                    criteria.setFirstResult(0);\r
-                }\r
-            }\r
-            List<DeterminationEvent> result = criteria.list();\r
-            defaultBeanInitializer.initializeAll(result, propertyPaths);\r
-            return result;\r
-        } else {\r
-            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(DeterminationEvent.class,auditEvent.getRevisionNumber());\r
-            if(occurrence != null) {\r
-                query.add(AuditEntity.relatedId("identifiedUnit").eq(occurrence.getId()));\r
-            }\r
-\r
-            if(taxonBase != null) {\r
-                query.add(AuditEntity.relatedId("taxon").eq(taxonBase.getId()));\r
-            }\r
-            if(pageSize != null) {\r
-                query.setMaxResults(pageSize);\r
-                if(pageNumber != null) {\r
-                    query.setFirstResult(pageNumber * pageSize);\r
-                } else {\r
-                    query.setFirstResult(0);\r
-                }\r
-            }\r
-            List<DeterminationEvent> result = query.getResultList();\r
-            defaultBeanInitializer.initializeAll(result, propertyPaths);\r
-            return result;\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public List<Media> getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {\r
-        checkNotInPriorView("OccurrenceDaoHibernateImpl.getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths)");\r
-        Query query = getSession().createQuery("select media from SpecimenOrObservationBase occurence join occurence.media media where occurence = :occurence");\r
-        query.setParameter("occurence", occurence);\r
-\r
-        if(pageSize != null) {\r
-            query.setMaxResults(pageSize);\r
-            if(pageNumber != null) {\r
-                query.setFirstResult(pageNumber * pageSize);\r
-            } else {\r
-                query.setFirstResult(0);\r
-            }\r
-        }\r
-\r
-        List<Media> results = query.list();\r
-        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-        return results;\r
-    }\r
-\r
-    @Override\r
-    public void rebuildIndex() {\r
-        FullTextSession fullTextSession = Search.getFullTextSession(getSession());\r
-\r
-        for(SpecimenOrObservationBase occurrence : list(null,null)) { // re-index all taxon base\r
-\r
-            for(DeterminationEvent determination : (Set<DeterminationEvent>)occurrence.getDeterminations()) {\r
-                Hibernate.initialize(determination.getActor());\r
-                Hibernate.initialize(determination.getTaxon());\r
-            }\r
-            Hibernate.initialize(occurrence.getDefinition());\r
-            if(occurrence instanceof DerivedUnit) {\r
-                DerivedUnit derivedUnit = (DerivedUnit) occurrence;\r
-                Hibernate.initialize(derivedUnit.getCollection());\r
-                if(derivedUnit.getCollection() != null) {\r
-                    Hibernate.initialize(derivedUnit.getCollection().getSuperCollection());\r
-                    Hibernate.initialize(derivedUnit.getCollection().getInstitute());\r
-                }\r
-                Hibernate.initialize(derivedUnit.getStoredUnder());\r
-                SpecimenOrObservationBase original = derivedUnit.getOriginalUnit();\r
-                if(original != null && original.isInstanceOf(FieldUnit.class)) {\r
-                    FieldUnit fieldUnit = original.deproxy(original, FieldUnit.class);\r
-                    Hibernate.initialize(fieldUnit.getGatheringEvent());\r
-                    if(fieldUnit.getGatheringEvent() != null) {\r
-                        Hibernate.initialize(fieldUnit.getGatheringEvent().getActor());\r
-                    }\r
-                }\r
-            }\r
-            fullTextSession.index(occurrence);\r
-        }\r
-        fullTextSession.flushToIndexes();\r
-    }\r
-\r
-    @Override\r
-    public int count(Class<? extends SpecimenOrObservationBase> clazz, TaxonBase determinedAs) {\r
-\r
-        Criteria criteria = null;\r
-        if(clazz == null) {\r
-            criteria = getSession().createCriteria(type);\r
-        } else {\r
-            criteria = getSession().createCriteria(clazz);\r
-        }\r
-\r
-        criteria.createCriteria("determinations").add(Restrictions.eq("taxon", determinedAs));\r
-        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));\r
-        return ((Number)criteria.uniqueResult()).intValue();\r
-    }\r
-\r
-    @Override\r
-    public List<SpecimenOrObservationBase> list(Class<? extends SpecimenOrObservationBase> clazz, TaxonBase determinedAs, Integer limit, Integer start,        List<OrderHint> orderHints, List<String> propertyPaths) {\r
-        Criteria criteria = null;\r
-        if(clazz == null) {\r
-            criteria = getSession().createCriteria(type);\r
-        } else {\r
-            criteria = getSession().createCriteria(clazz);\r
-        }\r
-\r
-        criteria.createCriteria("determinations").add(Restrictions.eq("taxon", determinedAs));\r
-\r
-        if(limit != null) {\r
-            if(start != null) {\r
-                criteria.setFirstResult(start);\r
-            } else {\r
-                criteria.setFirstResult(0);\r
-            }\r
-            criteria.setMaxResults(limit);\r
-        }\r
-\r
-        addOrder(criteria,orderHints);\r
-\r
-        List<SpecimenOrObservationBase> results = criteria.list();\r
-        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-        return results;\r
-    }\r
-\r
-    @Override\r
-    public <T extends SpecimenOrObservationBase> List<T> findOccurrences(Class<T> clazz, String queryString,\r
-            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon,\r
-            MatchMode matchmode, Integer limit,\r
-            Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-\r
-        Criteria criteria = createFindOccurrenceCriteria(clazz, queryString, significantIdentifier, recordBasis,\r
-                associatedTaxon, matchmode, limit, start, orderHints, propertyPaths);\r
-\r
-        if(criteria!=null){\r
-\r
-            if(limit != null) {\r
-                if(start != null) {\r
-                    criteria.setFirstResult(start);\r
-                } else {\r
-                    criteria.setFirstResult(0);\r
-                }\r
-                criteria.setMaxResults(limit);\r
-            }\r
-\r
-            if(orderHints!=null){\r
-                addOrder(criteria,orderHints);\r
-            }\r
-\r
-            List<T> results = criteria.list();\r
-            defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-            return results;\r
-        }\r
-        return Collections.EMPTY_LIST;\r
-    }\r
-\r
-    /**\r
-     * @param clazz\r
-     * @param queryString\r
-     * @param recordBasis\r
-     * @param associatedTaxon\r
-     * @param matchmode\r
-     * @param limit\r
-     * @param start\r
-     * @param orderHints\r
-     * @param propertyPaths\r
-     * @return\r
-     */\r
-    private <T extends SpecimenOrObservationBase> Criteria createFindOccurrenceCriteria(Class<T> clazz, String queryString,\r
-            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon, MatchMode matchmode, Integer limit,\r
-            Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-        Criteria criteria = null;\r
-\r
-        if(clazz == null) {\r
-            criteria = getSession().createCriteria(type);\r
-        } else {\r
-            criteria = getSession().createCriteria(clazz);\r
-        }\r
-\r
-        //queryString\r
-        if (queryString != null) {\r
-            if(matchmode == null) {\r
-                matchmode = MatchMode.ANYWHERE;\r
-                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));\r
-            } else if(matchmode == MatchMode.BEGINNING) {\r
-                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.START));\r
-            } else if(matchmode == MatchMode.END) {\r
-                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.END));\r
-            } else if(matchmode == MatchMode.EXACT) {\r
-                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.EXACT));\r
-            } else {\r
-                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.ANYWHERE));\r
-            }\r
-        }\r
-\r
-        //significant identifier\r
-        if (significantIdentifier != null) {\r
-            criteria.add(Restrictions.or(Restrictions.ilike("accessionNumber", significantIdentifier),\r
-                    Restrictions.ilike("catalogNumber", significantIdentifier), Restrictions.ilike("barcode", significantIdentifier)));\r
-        }\r
-\r
-        //recordBasis/SpecimenOrObservationType\r
-        if(recordBasis!=null){\r
-            Set<SpecimenOrObservationType> typeAndSubtypes = recordBasis.getGeneralizationOf(true);\r
-            typeAndSubtypes.add(recordBasis);\r
-            criteria.add(Restrictions.in("recordBasis", typeAndSubtypes));\r
-        }\r
-\r
-        //taxon associations\r
-        if(associatedTaxon!=null){\r
-            List<UUID> associatedTaxonUuids = new ArrayList<UUID>();\r
-            List<? extends SpecimenOrObservationBase> associatedTaxaList = listByAssociatedTaxon(clazz!=null?clazz:type, associatedTaxon, limit, start, orderHints, propertyPaths);\r
-            if(associatedTaxaList!=null){\r
-                for (SpecimenOrObservationBase specimenOrObservationBase : associatedTaxaList) {\r
-                    associatedTaxonUuids.add(specimenOrObservationBase.getUuid());\r
-                }\r
-            }\r
-            if(!associatedTaxonUuids.isEmpty()){\r
-                criteria.add(Restrictions.in("uuid", associatedTaxonUuids));\r
-            }\r
-            else{\r
-                return null;\r
-            }\r
-        }\r
-\r
-        return criteria;\r
-    }\r
-\r
-\r
-    @Override\r
-    public <T extends SpecimenOrObservationBase> int countOccurrences(Class<T> clazz, String queryString,\r
-            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon,\r
-            MatchMode matchmode, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-        Criteria criteria = createFindOccurrenceCriteria(clazz, queryString, significantIdentifier, recordBasis,\r
-                associatedTaxon, matchmode, limit, start, orderHints, propertyPaths);\r
-\r
-        if(criteria!=null){\r
-\r
-            criteria.setProjection(Projections.rowCount());\r
-\r
-            return ((Number)criteria.uniqueResult()).intValue();\r
-        }\r
-        return 0;\r
-    }\r
-\r
-    @Override\r
-    public List<UuidAndTitleCache<DerivedUnit>> getDerivedUnitUuidAndTitleCache() {\r
-        List<UuidAndTitleCache<DerivedUnit>> list = new ArrayList<UuidAndTitleCache<DerivedUnit>>();\r
-        Session session = getSession();\r
-\r
-        Query query = session.createQuery("select uuid, id, titleCache from " + type.getSimpleName() + " where NOT dtype = " + FieldUnit.class.getSimpleName());\r
-\r
-        List<Object[]> result = query.list();\r
-\r
-        for(Object[] object : result){\r
-            list.add(new UuidAndTitleCache<DerivedUnit>(DerivedUnit.class, (UUID) object[0], (Integer)object[1], (String) object[2]));\r
-        }\r
-\r
-        return list;\r
-    }\r
-\r
-    @Override\r
-    public List<UuidAndTitleCache<FieldUnit>> getFieldUnitUuidAndTitleCache() {\r
-        List<UuidAndTitleCache<FieldUnit>> list = new ArrayList<UuidAndTitleCache<FieldUnit>>();\r
-        Session session = getSession();\r
-\r
-        Query query = session.createQuery("select uuid, id, titleCache from " + type.getSimpleName() + " where dtype = " + FieldUnit.class.getSimpleName());\r
-\r
-        List<Object[]> result = query.list();\r
-\r
-        for(Object[] object : result){\r
-            list.add(new UuidAndTitleCache<FieldUnit>(FieldUnit.class, (UUID) object[0], (Integer)object[1], (String) object[2]));\r
-        }\r
-\r
-        return list;\r
-    }\r
-\r
-    @Override\r
-    public <T extends SpecimenOrObservationBase> List<T> listByAssociatedTaxon(Class<T> type,\r
-            Taxon associatedTaxon, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-\r
-        Set<SpecimenOrObservationBase> setOfAll = new HashSet<SpecimenOrObservationBase>();\r
-\r
-        // A Taxon may be referenced by the DeterminationEvent of the SpecimenOrObservationBase\r
-        List<SpecimenOrObservationBase> byDetermination = list(type, associatedTaxon, null, 0, null, null);\r
-        setOfAll.addAll(byDetermination);\r
-\r
-        // The IndividualsAssociation elements in a TaxonDescription contain DerivedUnits\r
-        List<IndividualsAssociation> byIndividualsAssociation = descriptionDao.getDescriptionElementForTaxon(\r
-                associatedTaxon.getUuid(), null, IndividualsAssociation.class, null, 0, null);\r
-        for(IndividualsAssociation individualsAssociation : byIndividualsAssociation){\r
-            setOfAll.add(individualsAssociation.getAssociatedSpecimenOrObservation());\r
-        }\r
-\r
-        // SpecimenTypeDesignations may be associated with the TaxonName.\r
-        List<SpecimenTypeDesignation> bySpecimenTypeDesignation = taxonNameDao.getTypeDesignations(associatedTaxon.getName(),\r
-                SpecimenTypeDesignation.class, null, null, 0, null);\r
-        for (SpecimenTypeDesignation specimenTypeDesignation : bySpecimenTypeDesignation) {\r
-            setOfAll.add(specimenTypeDesignation.getTypeSpecimen());\r
-        }\r
-\r
-        // SpecimenTypeDesignations may be associated with any HomotypicalGroup related to the specific Taxon.\r
-        for(HomotypicalGroup homotypicalGroup :  associatedTaxon.getHomotypicSynonymyGroups()) {\r
-            List<SpecimenTypeDesignation> byHomotypicalGroup = homotypicalGroupDao.getTypeDesignations(homotypicalGroup, SpecimenTypeDesignation.class, null, null, 0, null);\r
-            for (SpecimenTypeDesignation specimenTypeDesignation : byHomotypicalGroup) {\r
-                setOfAll.add(specimenTypeDesignation.getTypeSpecimen());\r
-            }\r
-        }\r
-\r
-        if(setOfAll.size() == 0){\r
-            // no need querying the data base\r
-            return new ArrayList<T>();\r
-        }\r
-\r
-        String queryString =\r
-            "select sob " +\r
-            " from SpecimenOrObservationBase sob" +\r
-            " where sob in (:setOfAll)";\r
-\r
-        if(type != null){\r
-            queryString += " and sob.class = :type";\r
-        }\r
-\r
-        if(orderHints != null && orderHints.size() > 0){\r
-            queryString += " order by ";\r
-            String orderStr = "";\r
-            for(OrderHint orderHint : orderHints){\r
-                if(orderStr.length() > 0){\r
-                    orderStr += ", ";\r
-                }\r
-                queryString += "sob." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();\r
-            }\r
-            queryString += orderStr;\r
-        }\r
-\r
-        Query query = getSession().createQuery(queryString);\r
-        query.setParameterList("setOfAll", setOfAll);\r
-\r
-        if(type != null){\r
-            query.setParameter("type", type.getSimpleName());\r
-        }\r
-\r
-        if(limit != null) {\r
-            if(start != null) {\r
-                query.setFirstResult(start);\r
-            } else {\r
-                query.setFirstResult(0);\r
-            }\r
-            query.setMaxResults(limit);\r
-        }\r
-\r
-\r
-        List<T> results = query.list();\r
-        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-        return results;\r
-    }\r
-\r
-    @Override\r
-    public Collection<SpecimenTypeDesignation> listBySpecimenOrObservationType(SpecimenOrObservationType type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-        String queryString = "FROM SpecimenOrObservationBase specimens WHERE specimens.recordBasis = :type";\r
-\r
-        if(orderHints != null && orderHints.size() > 0){\r
-            queryString += " order by ";\r
-            String orderStr = "";\r
-            for(OrderHint orderHint : orderHints){\r
-                if(orderStr.length() > 0){\r
-                    orderStr += ", ";\r
-                }\r
-                queryString += "specimens." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();\r
-            }\r
-            queryString += orderStr;\r
-        }\r
-\r
-        Query query = getSession().createQuery(queryString);\r
-        query.setParameter("type", type);\r
-\r
-        if(limit != null) {\r
-            if(start != null) {\r
-                query.setFirstResult(start);\r
-            } else {\r
-                query.setFirstResult(0);\r
-            }\r
-            query.setMaxResults(limit);\r
-        }\r
-\r
-        List results = query.list();\r
-        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-        return results;\r
-    }\r
-\r
-    @Override\r
-    public Collection<SpecimenTypeDesignation> listTypeDesignations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-        String queryString = "FROM SpecimenTypeDesignation designations WHERE designations.typeSpecimen = :specimen";\r
-\r
-        if(orderHints != null && orderHints.size() > 0){\r
-            queryString += " order by ";\r
-            String orderStr = "";\r
-            for(OrderHint orderHint : orderHints){\r
-                if(orderStr.length() > 0){\r
-                    orderStr += ", ";\r
-                }\r
-                queryString += "designations." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();\r
-            }\r
-            queryString += orderStr;\r
-        }\r
-\r
-        Query query = getSession().createQuery(queryString);\r
-        query.setParameter("specimen", specimen);\r
-\r
-        if(limit != null) {\r
-            if(start != null) {\r
-                query.setFirstResult(start);\r
-            } else {\r
-                query.setFirstResult(0);\r
-            }\r
-            query.setMaxResults(limit);\r
-        }\r
-\r
-        List results = query.list();\r
-        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-        return results;\r
-    }\r
-\r
-    @Override\r
-    public Collection<IndividualsAssociation> listIndividualsAssociations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-        //DISTINCT is necessary if more than one description exists for a taxon because we create the cross product of all taxon descriptions and description elements\r
-        String queryString = "FROM IndividualsAssociation associations WHERE associations.associatedSpecimenOrObservation = :specimen";\r
-\r
-        if(orderHints != null && orderHints.size() > 0){\r
-            queryString += " order by ";\r
-            String orderStr = "";\r
-            for(OrderHint orderHint : orderHints){\r
-                if(orderStr.length() > 0){\r
-                    orderStr += ", ";\r
-                }\r
-                queryString += "associations." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();\r
-            }\r
-            queryString += orderStr;\r
-        }\r
-\r
-        Query query = getSession().createQuery(queryString);\r
-        query.setParameter("specimen", specimen);\r
-\r
-        if(limit != null) {\r
-            if(start != null) {\r
-                query.setFirstResult(start);\r
-            } else {\r
-                query.setFirstResult(0);\r
-            }\r
-            query.setMaxResults(limit);\r
-        }\r
-\r
-        List results = query.list();\r
-        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-        return results;\r
-    }\r
-\r
-    @Override\r
-    public Collection<DescriptionBase<?>> listDescriptionsWithDescriptionSpecimen(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-        //DISTINCT is necessary if more than one description exists for a taxon because we create the cross product of all taxon descriptions and description elements\r
-        String queryString = "FROM DescriptionBase descriptions WHERE descriptions.describedSpecimenOrObservation = :specimen";\r
-\r
-        if(orderHints != null && orderHints.size() > 0){\r
-            queryString += " order by ";\r
-            String orderStr = "";\r
-            for(OrderHint orderHint : orderHints){\r
-                if(orderStr.length() > 0){\r
-                    orderStr += ", ";\r
-                }\r
-                queryString += "descriptions." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();\r
-            }\r
-            queryString += orderStr;\r
-        }\r
-\r
-        Query query = getSession().createQuery(queryString);\r
-        query.setParameter("specimen", specimen);\r
-\r
-        if(limit != null) {\r
-            if(start != null) {\r
-                query.setFirstResult(start);\r
-            } else {\r
-                query.setFirstResult(0);\r
-            }\r
-            query.setMaxResults(limit);\r
-        }\r
-\r
-        List results = query.list();\r
-        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-        return results;\r
-    }\r
-\r
+/**
+* Copyright (C) 2008 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*/
+
+package eu.etaxonomy.cdm.persistence.dao.hibernate.occurrence;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+import org.hibernate.Criteria;
+import org.hibernate.Hibernate;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.envers.query.AuditEntity;
+import org.hibernate.envers.query.AuditQuery;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import eu.etaxonomy.cdm.model.description.DescriptionBase;
+import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
+import eu.etaxonomy.cdm.model.media.Media;
+import eu.etaxonomy.cdm.model.molecular.DnaSample;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
+import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
+import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
+import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
+import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
+import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
+import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.model.view.AuditEvent;
+import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
+import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
+import eu.etaxonomy.cdm.persistence.dao.hibernate.taxon.TaxonDaoHibernateImpl;
+import eu.etaxonomy.cdm.persistence.dao.name.IHomotypicalGroupDao;
+import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
+import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;
+import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
+import eu.etaxonomy.cdm.persistence.query.MatchMode;
+import eu.etaxonomy.cdm.persistence.query.OrderHint;
+
+/**
+ * @author a.babadshanjan
+ * @created 01.09.2008
+ */
+@Repository
+public class OccurrenceDaoHibernateImpl extends IdentifiableDaoBase<SpecimenOrObservationBase> implements IOccurrenceDao {
+
+    @SuppressWarnings("unused")
+    private static final Logger logger = Logger.getLogger(TaxonDaoHibernateImpl.class);
+
+    @Autowired
+    private IDescriptionDao descriptionDao;
+
+    @Autowired
+    private ITaxonNameDao taxonNameDao;
+
+    @Autowired
+    private IHomotypicalGroupDao homotypicalGroupDao;
+
+    public OccurrenceDaoHibernateImpl() {
+        super(SpecimenOrObservationBase.class);
+        indexedClasses = new Class[7];
+        indexedClasses[0] = FieldUnit.class;
+        indexedClasses[1] = DerivedUnit.class;
+        indexedClasses[5] = DnaSample.class;
+    }
+
+    @Override
+    public int countDerivationEvents(SpecimenOrObservationBase occurence) {
+        checkNotInPriorView("OccurrenceDaoHibernateImpl.countDerivationEvents(SpecimenOrObservationBase occurence)");
+        Query query = getSession().createQuery("select count(distinct derivationEvent) from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");
+        query.setParameter("occurence", occurence);
+
+        return ((Long)query.uniqueResult()).intValue();
+    }
+
+    @Override
+    public int countDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase) {
+        AuditEvent auditEvent = getAuditEventFromContext();
+        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
+            Criteria criteria = getSession().createCriteria(DeterminationEvent.class);
+            if(occurrence != null) {
+                criteria.add(Restrictions.eq("identifiedUnit",occurrence));
+            }
+
+            if(taxonBase != null) {
+                criteria.add(Restrictions.eq("taxon",taxonBase));
+            }
+
+            criteria.setProjection(Projections.rowCount());
+            return ((Number)criteria.uniqueResult()).intValue();
+        } else {
+            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(DeterminationEvent.class,auditEvent.getRevisionNumber());
+
+            if(occurrence != null) {
+                query.add(AuditEntity.relatedId("identifiedUnit").eq(occurrence.getId()));
+            }
+
+            if(taxonBase != null) {
+                query.add(AuditEntity.relatedId("taxon").eq(taxonBase.getId()));
+            }
+            query.addProjection(AuditEntity.id().count("id"));
+
+            return ((Long)query.getSingleResult()).intValue();
+        }
+    }
+
+    @Override
+    public int countMedia(SpecimenOrObservationBase occurence) {
+        checkNotInPriorView("OccurrenceDaoHibernateImpl.countMedia(SpecimenOrObservationBase occurence)");
+        Query query = getSession().createQuery("select count(media) from SpecimenOrObservationBase occurence join occurence.media media where occurence = :occurence");
+        query.setParameter("occurence", occurence);
+
+        return ((Long)query.uniqueResult()).intValue();
+    }
+
+    @Override
+    public List<DerivationEvent> getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber, List<String> propertyPaths) {
+        checkNotInPriorView("OccurrenceDaoHibernateImpl.getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize,Integer pageNumber)");
+        Query query = getSession().createQuery("select distinct derivationEvent from DerivationEvent derivationEvent join derivationEvent.originals occurence where occurence = :occurence");
+        query.setParameter("occurence", occurence);
+
+        if(pageSize != null) {
+            query.setMaxResults(pageSize);
+            if(pageNumber != null) {
+                query.setFirstResult(pageNumber * pageSize);
+            } else {
+                query.setFirstResult(0);
+            }
+        }
+
+        List<DerivationEvent> result = query.list();
+        defaultBeanInitializer.initializeAll(result, propertyPaths);
+        return result;
+    }
+
+    @Override
+    public List<DeterminationEvent> getDeterminations(SpecimenOrObservationBase occurrence, TaxonBase taxonBase, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        AuditEvent auditEvent = getAuditEventFromContext();
+        if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
+            Criteria criteria = getSession().createCriteria(DeterminationEvent.class);
+            if(occurrence != null) {
+                criteria.add(Restrictions.eq("identifiedUnit",occurrence));
+            }
+
+            if(taxonBase != null) {
+                criteria.add(Restrictions.eq("taxon",taxonBase));
+            }
+
+            if(pageSize != null) {
+                criteria.setMaxResults(pageSize);
+                if(pageNumber != null) {
+                    criteria.setFirstResult(pageNumber * pageSize);
+                } else {
+                    criteria.setFirstResult(0);
+                }
+            }
+            List<DeterminationEvent> result = criteria.list();
+            defaultBeanInitializer.initializeAll(result, propertyPaths);
+            return result;
+        } else {
+            AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(DeterminationEvent.class,auditEvent.getRevisionNumber());
+            if(occurrence != null) {
+                query.add(AuditEntity.relatedId("identifiedUnit").eq(occurrence.getId()));
+            }
+
+            if(taxonBase != null) {
+                query.add(AuditEntity.relatedId("taxon").eq(taxonBase.getId()));
+            }
+            if(pageSize != null) {
+                query.setMaxResults(pageSize);
+                if(pageNumber != null) {
+                    query.setFirstResult(pageNumber * pageSize);
+                } else {
+                    query.setFirstResult(0);
+                }
+            }
+            List<DeterminationEvent> result = query.getResultList();
+            defaultBeanInitializer.initializeAll(result, propertyPaths);
+            return result;
+        }
+    }
+
+    @Override
+    public List<Media> getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        checkNotInPriorView("OccurrenceDaoHibernateImpl.getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths)");
+        Query query = getSession().createQuery("select media from SpecimenOrObservationBase occurence join occurence.media media where occurence = :occurence");
+        query.setParameter("occurence", occurence);
+
+        if(pageSize != null) {
+            query.setMaxResults(pageSize);
+            if(pageNumber != null) {
+                query.setFirstResult(pageNumber * pageSize);
+            } else {
+                query.setFirstResult(0);
+            }
+        }
+
+        List<Media> results = query.list();
+        defaultBeanInitializer.initializeAll(results, propertyPaths);
+        return results;
+    }
+
+    @Override
+    public void rebuildIndex() {
+        FullTextSession fullTextSession = Search.getFullTextSession(getSession());
+
+        for(SpecimenOrObservationBase occurrence : list(null,null)) { // re-index all taxon base
+
+            for(DeterminationEvent determination : (Set<DeterminationEvent>)occurrence.getDeterminations()) {
+                Hibernate.initialize(determination.getActor());
+                Hibernate.initialize(determination.getTaxon());
+            }
+            Hibernate.initialize(occurrence.getDefinition());
+            if(occurrence instanceof DerivedUnit) {
+                DerivedUnit derivedUnit = (DerivedUnit) occurrence;
+                Hibernate.initialize(derivedUnit.getCollection());
+                if(derivedUnit.getCollection() != null) {
+                    Hibernate.initialize(derivedUnit.getCollection().getSuperCollection());
+                    Hibernate.initialize(derivedUnit.getCollection().getInstitute());
+                }
+                Hibernate.initialize(derivedUnit.getStoredUnder());
+                SpecimenOrObservationBase original = derivedUnit.getOriginalUnit();
+                if(original != null && original.isInstanceOf(FieldUnit.class)) {
+                    FieldUnit fieldUnit = original.deproxy(original, FieldUnit.class);
+                    Hibernate.initialize(fieldUnit.getGatheringEvent());
+                    if(fieldUnit.getGatheringEvent() != null) {
+                        Hibernate.initialize(fieldUnit.getGatheringEvent().getActor());
+                    }
+                }
+            }
+            fullTextSession.index(occurrence);
+        }
+        fullTextSession.flushToIndexes();
+    }
+
+    @Override
+    public int count(Class<? extends SpecimenOrObservationBase> clazz, TaxonBase determinedAs) {
+
+        Criteria criteria = null;
+        if(clazz == null) {
+            criteria = getSession().createCriteria(type);
+        } else {
+            criteria = getSession().createCriteria(clazz);
+        }
+
+        criteria.createCriteria("determinations").add(Restrictions.eq("taxon", determinedAs));
+        criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));
+        return ((Number)criteria.uniqueResult()).intValue();
+    }
+
+    @Override
+    public List<SpecimenOrObservationBase> list(Class<? extends SpecimenOrObservationBase> clazz, TaxonBase determinedAs, Integer limit, Integer start,        List<OrderHint> orderHints, List<String> propertyPaths) {
+        Criteria criteria = null;
+        if(clazz == null) {
+            criteria = getSession().createCriteria(type);
+        } else {
+            criteria = getSession().createCriteria(clazz);
+        }
+
+        criteria.createCriteria("determinations").add(Restrictions.eq("taxon", determinedAs));
+
+        if(limit != null) {
+            if(start != null) {
+                criteria.setFirstResult(start);
+            } else {
+                criteria.setFirstResult(0);
+            }
+            criteria.setMaxResults(limit);
+        }
+
+        addOrder(criteria,orderHints);
+
+        List<SpecimenOrObservationBase> results = criteria.list();
+        defaultBeanInitializer.initializeAll(results, propertyPaths);
+        return results;
+    }
+
+    @Override
+    public <T extends SpecimenOrObservationBase> List<T> findOccurrences(Class<T> clazz, String queryString,
+            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon,
+            MatchMode matchmode, Integer limit,
+            Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+
+        Criteria criteria = createFindOccurrenceCriteria(clazz, queryString, significantIdentifier, recordBasis,
+                associatedTaxon, matchmode, limit, start, orderHints, propertyPaths);
+
+        if(criteria!=null){
+
+            if(limit != null) {
+                if(start != null) {
+                    criteria.setFirstResult(start);
+                } else {
+                    criteria.setFirstResult(0);
+                }
+                criteria.setMaxResults(limit);
+            }
+
+            if(orderHints!=null){
+                addOrder(criteria,orderHints);
+            }
+
+            List<T> results = criteria.list();
+            defaultBeanInitializer.initializeAll(results, propertyPaths);
+            return results;
+        }
+        return Collections.EMPTY_LIST;
+    }
+
+    /**
+     * @param clazz
+     * @param queryString
+     * @param recordBasis
+     * @param associatedTaxon
+     * @param matchmode
+     * @param limit
+     * @param start
+     * @param orderHints
+     * @param propertyPaths
+     * @return
+     */
+    private <T extends SpecimenOrObservationBase> Criteria createFindOccurrenceCriteria(Class<T> clazz, String queryString,
+            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon, MatchMode matchmode, Integer limit,
+            Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+        Criteria criteria = null;
+
+        if(clazz == null) {
+            criteria = getSession().createCriteria(type);
+        } else {
+            criteria = getSession().createCriteria(clazz);
+        }
+
+        //queryString
+        if (queryString != null) {
+            if(matchmode == null) {
+                matchmode = MatchMode.ANYWHERE;
+                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
+            } else if(matchmode == MatchMode.BEGINNING) {
+                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.START));
+            } else if(matchmode == MatchMode.END) {
+                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.END));
+            } else if(matchmode == MatchMode.EXACT) {
+                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.EXACT));
+            } else {
+                criteria.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.ANYWHERE));
+            }
+        }
+
+        //significant identifier
+        if (significantIdentifier != null) {
+            criteria.add(Restrictions.or(Restrictions.ilike("accessionNumber", significantIdentifier),
+                    Restrictions.ilike("catalogNumber", significantIdentifier), Restrictions.ilike("barcode", significantIdentifier)));
+        }
+
+        //recordBasis/SpecimenOrObservationType
+        if(recordBasis!=null){
+            Set<SpecimenOrObservationType> typeAndSubtypes = recordBasis.getGeneralizationOf(true);
+            typeAndSubtypes.add(recordBasis);
+            criteria.add(Restrictions.in("recordBasis", typeAndSubtypes));
+        }
+
+        //taxon associations
+        if(associatedTaxon!=null){
+            List<UUID> associatedTaxonUuids = new ArrayList<UUID>();
+            List<? extends SpecimenOrObservationBase> associatedTaxaList = listByAssociatedTaxon(clazz!=null?clazz:type, associatedTaxon, limit, start, orderHints, propertyPaths);
+            if(associatedTaxaList!=null){
+                for (SpecimenOrObservationBase specimenOrObservationBase : associatedTaxaList) {
+                    associatedTaxonUuids.add(specimenOrObservationBase.getUuid());
+                }
+            }
+            if(!associatedTaxonUuids.isEmpty()){
+                criteria.add(Restrictions.in("uuid", associatedTaxonUuids));
+            }
+            else{
+                return null;
+            }
+        }
+
+        return criteria;
+    }
+
+
+    @Override
+    public <T extends SpecimenOrObservationBase> int countOccurrences(Class<T> clazz, String queryString,
+            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon,
+            MatchMode matchmode, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+        Criteria criteria = createFindOccurrenceCriteria(clazz, queryString, significantIdentifier, recordBasis,
+                associatedTaxon, matchmode, limit, start, orderHints, propertyPaths);
+
+        if(criteria!=null){
+
+            criteria.setProjection(Projections.rowCount());
+
+            return ((Number)criteria.uniqueResult()).intValue();
+        }
+        return 0;
+    }
+
+    @Override
+    public List<UuidAndTitleCache<DerivedUnit>> getDerivedUnitUuidAndTitleCache() {
+        List<UuidAndTitleCache<DerivedUnit>> list = new ArrayList<UuidAndTitleCache<DerivedUnit>>();
+        Session session = getSession();
+
+        Query query = session.createQuery("select uuid, id, titleCache from " + type.getSimpleName() + " where NOT dtype = " + FieldUnit.class.getSimpleName());
+
+        List<Object[]> result = query.list();
+
+        for(Object[] object : result){
+            list.add(new UuidAndTitleCache<DerivedUnit>(DerivedUnit.class, (UUID) object[0], (Integer)object[1], (String) object[2]));
+        }
+
+        return list;
+    }
+
+    @Override
+    public List<UuidAndTitleCache<FieldUnit>> getFieldUnitUuidAndTitleCache() {
+        List<UuidAndTitleCache<FieldUnit>> list = new ArrayList<UuidAndTitleCache<FieldUnit>>();
+        Session session = getSession();
+
+        Query query = session.createQuery("select uuid, id, titleCache from " + type.getSimpleName() + " where dtype = " + FieldUnit.class.getSimpleName());
+
+        List<Object[]> result = query.list();
+
+        for(Object[] object : result){
+            list.add(new UuidAndTitleCache<FieldUnit>(FieldUnit.class, (UUID) object[0], (Integer)object[1], (String) object[2]));
+        }
+
+        return list;
+    }
+
+    @Override
+    public <T extends SpecimenOrObservationBase> List<T> listByAssociatedTaxon(Class<T> type,
+            Taxon associatedTaxon, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+
+        Set<SpecimenOrObservationBase> setOfAll = new HashSet<SpecimenOrObservationBase>();
+
+        // A Taxon may be referenced by the DeterminationEvent of the SpecimenOrObservationBase
+        List<SpecimenOrObservationBase> byDetermination = list(type, associatedTaxon, null, 0, null, null);
+        setOfAll.addAll(byDetermination);
+
+        // The IndividualsAssociation elements in a TaxonDescription contain DerivedUnits
+        List<IndividualsAssociation> byIndividualsAssociation = descriptionDao.getDescriptionElementForTaxon(
+                associatedTaxon.getUuid(), null, IndividualsAssociation.class, null, 0, null);
+        for(IndividualsAssociation individualsAssociation : byIndividualsAssociation){
+            setOfAll.add(individualsAssociation.getAssociatedSpecimenOrObservation());
+        }
+
+        // SpecimenTypeDesignations may be associated with the TaxonName.
+        List<SpecimenTypeDesignation> bySpecimenTypeDesignation = taxonNameDao.getTypeDesignations(associatedTaxon.getName(),
+                SpecimenTypeDesignation.class, null, null, 0, null);
+        for (SpecimenTypeDesignation specimenTypeDesignation : bySpecimenTypeDesignation) {
+            setOfAll.add(specimenTypeDesignation.getTypeSpecimen());
+        }
+
+        // SpecimenTypeDesignations may be associated with any HomotypicalGroup related to the specific Taxon.
+        for(HomotypicalGroup homotypicalGroup :  associatedTaxon.getHomotypicSynonymyGroups()) {
+            List<SpecimenTypeDesignation> byHomotypicalGroup = homotypicalGroupDao.getTypeDesignations(homotypicalGroup, SpecimenTypeDesignation.class, null, null, 0, null);
+            for (SpecimenTypeDesignation specimenTypeDesignation : byHomotypicalGroup) {
+                setOfAll.add(specimenTypeDesignation.getTypeSpecimen());
+            }
+        }
+
+        if(setOfAll.size() == 0){
+            // no need querying the data base
+            return new ArrayList<T>();
+        }
+
+        String queryString =
+            "select sob " +
+            " from SpecimenOrObservationBase sob" +
+            " where sob in (:setOfAll)";
+
+        if(type != null){
+            queryString += " and sob.class = :type";
+        }
+
+        if(orderHints != null && orderHints.size() > 0){
+            queryString += " order by ";
+            String orderStr = "";
+            for(OrderHint orderHint : orderHints){
+                if(orderStr.length() > 0){
+                    orderStr += ", ";
+                }
+                queryString += "sob." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
+            }
+            queryString += orderStr;
+        }
+
+        Query query = getSession().createQuery(queryString);
+        query.setParameterList("setOfAll", setOfAll);
+
+        if(type != null){
+            query.setParameter("type", type.getSimpleName());
+        }
+
+        if(limit != null) {
+            if(start != null) {
+                query.setFirstResult(start);
+            } else {
+                query.setFirstResult(0);
+            }
+            query.setMaxResults(limit);
+        }
+
+
+        List<T> results = query.list();
+        defaultBeanInitializer.initializeAll(results, propertyPaths);
+        return results;
+    }
+
+    @Override
+    public Collection<SpecimenOrObservationBase> listBySpecimenOrObservationType(SpecimenOrObservationType type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+        String queryString = "FROM SpecimenOrObservationBase specimens WHERE specimens.recordBasis = :type";
+
+        if(orderHints != null && orderHints.size() > 0){
+            queryString += " order by ";
+            String orderStr = "";
+            for(OrderHint orderHint : orderHints){
+                if(orderStr.length() > 0){
+                    orderStr += ", ";
+                }
+                queryString += "specimens." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
+            }
+            queryString += orderStr;
+        }
+
+        Query query = getSession().createQuery(queryString);
+        query.setParameter("type", type);
+
+        if(limit != null) {
+            if(start != null) {
+                query.setFirstResult(start);
+            } else {
+                query.setFirstResult(0);
+            }
+            query.setMaxResults(limit);
+        }
+
+        List results = query.list();
+        defaultBeanInitializer.initializeAll(results, propertyPaths);
+        return results;
+    }
+
+    @Override
+    public Collection<SpecimenTypeDesignation> listTypeDesignations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+        String queryString = "FROM SpecimenTypeDesignation designations WHERE designations.typeSpecimen = :specimen";
+
+        if(orderHints != null && orderHints.size() > 0){
+            queryString += " order by ";
+            String orderStr = "";
+            for(OrderHint orderHint : orderHints){
+                if(orderStr.length() > 0){
+                    orderStr += ", ";
+                }
+                queryString += "designations." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
+            }
+            queryString += orderStr;
+        }
+
+        Query query = getSession().createQuery(queryString);
+        query.setParameter("specimen", specimen);
+
+        if(limit != null) {
+            if(start != null) {
+                query.setFirstResult(start);
+            } else {
+                query.setFirstResult(0);
+            }
+            query.setMaxResults(limit);
+        }
+
+        List results = query.list();
+        defaultBeanInitializer.initializeAll(results, propertyPaths);
+        return results;
+    }
+
+    @Override
+    public Collection<IndividualsAssociation> listIndividualsAssociations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+        //DISTINCT is necessary if more than one description exists for a taxon because we create the cross product of all taxon descriptions and description elements
+        String queryString = "FROM IndividualsAssociation associations WHERE associations.associatedSpecimenOrObservation = :specimen";
+
+        if(orderHints != null && orderHints.size() > 0){
+            queryString += " order by ";
+            String orderStr = "";
+            for(OrderHint orderHint : orderHints){
+                if(orderStr.length() > 0){
+                    orderStr += ", ";
+                }
+                queryString += "associations." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
+            }
+            queryString += orderStr;
+        }
+
+        Query query = getSession().createQuery(queryString);
+        query.setParameter("specimen", specimen);
+
+        if(limit != null) {
+            if(start != null) {
+                query.setFirstResult(start);
+            } else {
+                query.setFirstResult(0);
+            }
+            query.setMaxResults(limit);
+        }
+
+        List results = query.list();
+        defaultBeanInitializer.initializeAll(results, propertyPaths);
+        return results;
+    }
+
+    @Override
+    public Collection<DescriptionBase<?>> listDescriptionsWithDescriptionSpecimen(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
+        //DISTINCT is necessary if more than one description exists for a taxon because we create the cross product of all taxon descriptions and description elements
+        String queryString = "FROM DescriptionBase descriptions WHERE descriptions.describedSpecimenOrObservation = :specimen";
+
+        if(orderHints != null && orderHints.size() > 0){
+            queryString += " order by ";
+            String orderStr = "";
+            for(OrderHint orderHint : orderHints){
+                if(orderStr.length() > 0){
+                    orderStr += ", ";
+                }
+                queryString += "descriptions." + orderHint.getPropertyName() + " " + orderHint.getSortOrder().toHql();
+            }
+            queryString += orderStr;
+        }
+
+        Query query = getSession().createQuery(queryString);
+        query.setParameter("specimen", specimen);
+
+        if(limit != null) {
+            if(start != null) {
+                query.setFirstResult(start);
+            } else {
+                query.setFirstResult(0);
+            }
+            query.setMaxResults(limit);
+        }
+
+        List results = query.list();
+        defaultBeanInitializer.initializeAll(results, propertyPaths);
+        return results;
+    }
+
 }
\ No newline at end of file
index 3b032377f4e7d8ad1028cc82d624cc1d364b891f..0b6a149e7af3876cc88c05109bee0f8e7d1dc1c5 100644 (file)
-/**\r
-* Copyright (C) 2008 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*/\r
-\r
-package eu.etaxonomy.cdm.persistence.dao.occurrence;\r
-\r
-import java.util.Collection;\r
-import java.util.List;\r
-import java.util.UUID;\r
-\r
-import org.springframework.dao.DataAccessException;\r
-\r
-import eu.etaxonomy.cdm.model.description.DescriptionBase;\r
-import eu.etaxonomy.cdm.model.description.IndividualsAssociation;\r
-import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
-import eu.etaxonomy.cdm.model.media.Media;\r
-import eu.etaxonomy.cdm.model.name.HomotypicalGroup;\r
-import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;\r
-import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;\r
-import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
-import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
-import eu.etaxonomy.cdm.model.occurrence.FieldUnit;\r
-import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;\r
-import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;\r
-import eu.etaxonomy.cdm.model.taxon.Taxon;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
-import eu.etaxonomy.cdm.persistence.dao.common.IIdentifiableDao;\r
-import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;\r
-import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;\r
-import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
-import eu.etaxonomy.cdm.persistence.query.OrderHint;\r
-\r
-/**\r
- * @author a.babadshanjan\r
- * @created 01.09.2008\r
- */\r
-public interface IOccurrenceDao extends IIdentifiableDao<SpecimenOrObservationBase> {\r
-\r
-       /**\r
-        * Returns the number of occurences belonging to a certain subclass - which must extend SpecimenOrObservationBase\r
-        * @param clazz optionally restrict the counted occurrences to those of a certain subclass of SpecimenOrObservationBase\r
-        * @param determinedAs the taxon concept that these specimens are determined to belong to\r
-        * @return\r
-        */\r
-       public int count(Class<? extends SpecimenOrObservationBase> clazz,TaxonBase determinedAs);\r
-\r
-       /**\r
-        * Returns a sublist of SpecimenOrObservationBase instances stored in the database. A maximum\r
-        * of 'limit' objects are returned, starting at object with index 'start'. Only occurrences which\r
-        * have been determined to belong to the supplied concept are returned.\r
-        *\r
-        * @param type\r
-        * @param determinedAs the taxon concept that these specimens are determined to belong to\r
-        * @param limit\r
-        *            the maximum number of entities returned (can be null to return\r
-        *            all entities)\r
-        * @param start\r
-        * @param orderHints\r
-        *            Supports path like <code>orderHints.propertyNames</code> which\r
-        *            include *-to-one properties like createdBy.username or\r
-        *            authorTeam.persistentTitleCache\r
-        * @return\r
-        * @throws DataAccessException\r
-        */\r
-       public List<SpecimenOrObservationBase> list(Class<? extends SpecimenOrObservationBase> type, TaxonBase determinedAs, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-\r
-           /**\r
-     * Queries the database for specimens which match the given criteria\r
-     *\r
-     * @param clazz\r
-     *            the class to match\r
-     * @param queryString\r
-     *            the queryString to match\r
-     * @param type\r
-     *            the {@link SpecimenOrObservationType} to match\r
-     * @param associatedTaxon\r
-     *            the taxon these specimens are in any way associated to via\r
-     *            determination, type designations, individuals associations,\r
-     *            etc.\r
-     * @param matchmode\r
-     *            determines how the query string should be matched\r
-     * @param limit\r
-     *            the maximum number of entities returned (can be null to return\r
-     *            all entities)\r
-     * @param start\r
-     * @param orderHints\r
-     *            Supports path like <code>orderHints.propertyNames</code> which\r
-     *            include *-to-one properties like createdBy.username or\r
-     *            authorTeam.persistentTitleCache\r
-     * @param propertyPaths\r
-     * @return a list of specimens that match the given parameters\r
-     */\r
-    public <T extends SpecimenOrObservationBase> List<T> findOccurrences(Class<T> clazz, String queryString,\r
-            String significantIdentifier, SpecimenOrObservationType type, Taxon determinedAs, MatchMode matchmode,\r
-            Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-\r
-       /**\r
-        * Returns the number of specimens that match the given parameters\r
-        * @param clazz the class to match\r
-     * @param queryString the queryString to match\r
-     * @param type the {@link SpecimenOrObservationType} to match\r
-     * @param associatedTaxon the taxon these specimens are in any way associated to via\r
-     * determination, type designations, individuals associations, etc.\r
-     * @param matchmode determines how the query string should be matched\r
-     * @param limit\r
-     *            the maximum number of entities returned (can be null to return\r
-     *            all entities)\r
-     * @param start\r
-     * @param orderHints\r
-     *            Supports path like <code>orderHints.propertyNames</code> which\r
-     *            include *-to-one properties like createdBy.username or\r
-     *            authorTeam.persistentTitleCache\r
-        * @return the number of found specimens\r
-        */\r
-    public <T extends SpecimenOrObservationBase> int countOccurrences(Class<T> clazz, String queryString,\r
-            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon,\r
-            MatchMode matchmode, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-\r
-       /**\r
-     * Returns a count of Media that are associated with a given occurence\r
-     *\r
-        * @param occurence the occurence associated with these media\r
-     * @return a count of media instances\r
-     */\r
-       public int countMedia(SpecimenOrObservationBase occurence);\r
-\r
-    /**\r
-     * Returns a List of Media that are associated with a given occurence\r
-     *\r
-        * @param occurence the occurence associated with these media\r
-        * @param pageSize The maximum number of media returned (can be null for all related media)\r
-        * @param pageNumber The offset (in pageSize chunks) from the start of the result set (0 - based)\r
-        * @param propertyPaths properties to initialize - see {@link IBeanInitializer#initialize(Object, List)}\r
-     * @return a List of media instances\r
-     */\r
-       public List<Media> getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths);\r
-\r
-       /**\r
-     * Returns a count of determinations that have been made for a given occurence and for a given taxon concept\r
-     *\r
-        * @param occurence the occurence associated with these determinations (can be null for all occurrences)\r
-        * @param taxonbase the taxon concept associated with these determinations (can be null for all taxon concepts)\r
-     * @return a count of determination events\r
-     */\r
-    public int countDeterminations(SpecimenOrObservationBase occurence,TaxonBase taxonbase);\r
-\r
-    /**\r
-     * Returns a List of determinations that have been made for a given occurence and for a given taxon concept\r
-     *\r
-        * @param occurence the occurence associated with these determinations (can be null for all occurrences)\r
-        * @param taxonbase the taxon concept associated with these determinations (can be null for all taxon concepts)\r
-        * @param pageSize The maximum number of determinations returned (can be null for all related determinations)\r
-        * @param pageNumber The offset (in pageSize chunks) from the start of the result set (0 - based)\r
-        * @param propertyPaths properties to initialize - see {@link IBeanInitializer#initialize(Object, List)}\r
-     * @return a List of determination instances\r
-     */\r
-       public List<DeterminationEvent> getDeterminations(SpecimenOrObservationBase occurence,TaxonBase taxonbase, Integer pageSize, Integer pageNumber, List<String> propertyPaths);\r
-\r
-       /**\r
-     * Returns a count of derivation events that have involved creating new DerivedUnits from this occurence\r
-     *\r
-        * @param occurence the occurence that was a source of these derivation events\r
-     * @return a count of derivation events\r
-     */\r
-    public int countDerivationEvents(SpecimenOrObservationBase occurence);\r
-\r
-    /**\r
-     * Returns a list of derivation events that have involved creating new DerivedUnits from this occurence\r
-     *\r
-        * @param occurence the occurence that was a source of these derivation events\r
-        * @param pageSize The maximum number of derivation events returned (can be null for all related derivation events)\r
-        * @param pageNumber The offset (in pageSize chunks) from the start of the result set (0 - based)\r
-        * @param propertyPaths properties to initialize - see {@link IBeanInitializer#initialize(Object, List)}\r
-     * @return a List of derivation events\r
-     */\r
-       public List<DerivationEvent> getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths);\r
-\r
-    /**\r
-     * Retrieves the {@link UUID} and the string representation (title cache) of all\r
-     * {@link FieldUnit}s found in the data base.\r
-     * @return a list of {@link UuidAndTitleCache}\r
-     */\r
-       public List<UuidAndTitleCache<FieldUnit>> getFieldUnitUuidAndTitleCache();\r
-\r
-    /**\r
-     * Retrieves the {@link UUID} and the string representation (title cache) of all\r
-     * {@link DerivedUnit}s found in the data base.\r
-     * @return a list of {@link UuidAndTitleCache}\r
-     */\r
-       public List<UuidAndTitleCache<DerivedUnit>> getDerivedUnitUuidAndTitleCache();\r
-\r
-       /**\r
-        * Lists all instances of {@link SpecimenOrObservationBase} which are associated with the <code>taxon</code> specified as parameter.\r
-        * SpecimenOrObservationBase instances can be associated to taxa in multiple ways, all these possible relations are taken into account:\r
-        * <ul>\r
-        * <li>The {@link IndividualsAssociation} elements in a {@link TaxonDescription} contain {@link DerivedUnit}s</li>\r
-        * <li>{@link SpecimenTypeDesignation}s may be associated with any {@link HomotypicalGroup} related to the specific {@link Taxon}.</li>\r
-        * <li>A {@link Taxon} may be referenced by the {@link DeterminationEvent} of the {@link SpecimenOrObservationBase}</li>\r
-        * </ul>\r
-        *\r
-        * @param <T>\r
-        * @param type\r
-        * @param associatedTaxon\r
-        * @param limit\r
-        * @param start\r
-        * @param orderHints\r
-        * @param propertyPaths\r
-        * @return\r
-        */\r
-       public <T extends SpecimenOrObservationBase> List<T> listByAssociatedTaxon(Class<T> type, Taxon associatedTaxon,\r
-                       Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-\r
-    /**\r
-     * Retrieves all {@link IndividualsAssociation} with the given specimen.<br>\r
-     * @param specimen the specimen for which the associations are retrieved\r
-     * @param limit\r
-     * @param start\r
-     * @param orderHints\r
-     * @param propertyPaths\r
-     * @return collection of all associations\r
-     */\r
-       public Collection<IndividualsAssociation> listIndividualsAssociations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-\r
-    /**\r
-     * Retrieves all {@link SpecimenTypeDesignation}s which have the given specimen as a type specimen.\r
-     * @param specimen the type specimen\r
-     * @param limit\r
-     * @param start\r
-     * @param orderHints\r
-     * @param propertyPaths\r
-     * @return collection of all designations with the given type specimen\r
-     */\r
-    public Collection<SpecimenTypeDesignation> listTypeDesignations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-\r
-    /**\r
-     * Retrieves all {@link DescriptionBase}s that have the given specimen set as described specimen.\r
-     * @param specimen the described specimen\r
-     * @param limit\r
-     * @param start\r
-     * @param orderHints\r
-     * @param propertyPaths\r
-     * @return collection of all descriptions with the given described specimen\r
-     */\r
-    public Collection<DescriptionBase<?>> listDescriptionsWithDescriptionSpecimen(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-\r
-    /**\r
-     * Retrieves all {@link SpecimenOrObservationBase}s that have the given {@link SpecimenOrObservationType}.\r
-     * @param type\r
-     * @param limit\r
-     * @param start\r
-     * @param orderHints\r
-     * @param propertyPaths\r
-     * @return collection of specimen with the given type\r
-     */\r
-    public Collection<SpecimenTypeDesignation> listBySpecimenOrObservationType(SpecimenOrObservationType type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
-}\r
+/**
+* Copyright (C) 2008 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*/
+
+package eu.etaxonomy.cdm.persistence.dao.occurrence;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import org.springframework.dao.DataAccessException;
+
+import eu.etaxonomy.cdm.model.description.DescriptionBase;
+import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
+import eu.etaxonomy.cdm.model.media.Media;
+import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
+import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
+import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
+import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
+import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
+import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
+import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
+import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.persistence.dao.common.IIdentifiableDao;
+import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
+import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
+import eu.etaxonomy.cdm.persistence.query.MatchMode;
+import eu.etaxonomy.cdm.persistence.query.OrderHint;
+
+/**
+ * @author a.babadshanjan
+ * @created 01.09.2008
+ */
+public interface IOccurrenceDao extends IIdentifiableDao<SpecimenOrObservationBase> {
+
+       /**
+        * Returns the number of occurences belonging to a certain subclass - which must extend SpecimenOrObservationBase
+        * @param clazz optionally restrict the counted occurrences to those of a certain subclass of SpecimenOrObservationBase
+        * @param determinedAs the taxon concept that these specimens are determined to belong to
+        * @return
+        */
+       public int count(Class<? extends SpecimenOrObservationBase> clazz,TaxonBase determinedAs);
+
+       /**
+        * Returns a sublist of SpecimenOrObservationBase instances stored in the database. A maximum
+        * of 'limit' objects are returned, starting at object with index 'start'. Only occurrences which
+        * have been determined to belong to the supplied concept are returned.
+        *
+        * @param type
+        * @param determinedAs the taxon concept that these specimens are determined to belong to
+        * @param limit
+        *            the maximum number of entities returned (can be null to return
+        *            all entities)
+        * @param start
+        * @param orderHints
+        *            Supports path like <code>orderHints.propertyNames</code> which
+        *            include *-to-one properties like createdBy.username or
+        *            authorTeam.persistentTitleCache
+        * @return
+        * @throws DataAccessException
+        */
+       public List<SpecimenOrObservationBase> list(Class<? extends SpecimenOrObservationBase> type, TaxonBase determinedAs, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+
+           /**
+     * Queries the database for specimens which match the given criteria
+     *
+     * @param clazz
+     *            the class to match
+     * @param queryString
+     *            the queryString to match
+     * @param type
+     *            the {@link SpecimenOrObservationType} to match
+     * @param associatedTaxon
+     *            the taxon these specimens are in any way associated to via
+     *            determination, type designations, individuals associations,
+     *            etc.
+     * @param matchmode
+     *            determines how the query string should be matched
+     * @param limit
+     *            the maximum number of entities returned (can be null to return
+     *            all entities)
+     * @param start
+     * @param orderHints
+     *            Supports path like <code>orderHints.propertyNames</code> which
+     *            include *-to-one properties like createdBy.username or
+     *            authorTeam.persistentTitleCache
+     * @param propertyPaths
+     * @return a list of specimens that match the given parameters
+     */
+    public <T extends SpecimenOrObservationBase> List<T> findOccurrences(Class<T> clazz, String queryString,
+            String significantIdentifier, SpecimenOrObservationType type, Taxon determinedAs, MatchMode matchmode,
+            Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+
+       /**
+        * Returns the number of specimens that match the given parameters
+        * @param clazz the class to match
+     * @param queryString the queryString to match
+     * @param type the {@link SpecimenOrObservationType} to match
+     * @param associatedTaxon the taxon these specimens are in any way associated to via
+     * determination, type designations, individuals associations, etc.
+     * @param matchmode determines how the query string should be matched
+     * @param limit
+     *            the maximum number of entities returned (can be null to return
+     *            all entities)
+     * @param start
+     * @param orderHints
+     *            Supports path like <code>orderHints.propertyNames</code> which
+     *            include *-to-one properties like createdBy.username or
+     *            authorTeam.persistentTitleCache
+        * @return the number of found specimens
+        */
+    public <T extends SpecimenOrObservationBase> int countOccurrences(Class<T> clazz, String queryString,
+            String significantIdentifier, SpecimenOrObservationType recordBasis, Taxon associatedTaxon,
+            MatchMode matchmode, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+
+       /**
+     * Returns a count of Media that are associated with a given occurence
+     *
+        * @param occurence the occurence associated with these media
+     * @return a count of media instances
+     */
+       public int countMedia(SpecimenOrObservationBase occurence);
+
+    /**
+     * Returns a List of Media that are associated with a given occurence
+     *
+        * @param occurence the occurence associated with these media
+        * @param pageSize The maximum number of media returned (can be null for all related media)
+        * @param pageNumber The offset (in pageSize chunks) from the start of the result set (0 - based)
+        * @param propertyPaths properties to initialize - see {@link IBeanInitializer#initialize(Object, List)}
+     * @return a List of media instances
+     */
+       public List<Media> getMedia(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths);
+
+       /**
+     * Returns a count of determinations that have been made for a given occurence and for a given taxon concept
+     *
+        * @param occurence the occurence associated with these determinations (can be null for all occurrences)
+        * @param taxonbase the taxon concept associated with these determinations (can be null for all taxon concepts)
+     * @return a count of determination events
+     */
+    public int countDeterminations(SpecimenOrObservationBase occurence,TaxonBase taxonbase);
+
+    /**
+     * Returns a List of determinations that have been made for a given occurence and for a given taxon concept
+     *
+        * @param occurence the occurence associated with these determinations (can be null for all occurrences)
+        * @param taxonbase the taxon concept associated with these determinations (can be null for all taxon concepts)
+        * @param pageSize The maximum number of determinations returned (can be null for all related determinations)
+        * @param pageNumber The offset (in pageSize chunks) from the start of the result set (0 - based)
+        * @param propertyPaths properties to initialize - see {@link IBeanInitializer#initialize(Object, List)}
+     * @return a List of determination instances
+     */
+       public List<DeterminationEvent> getDeterminations(SpecimenOrObservationBase occurence,TaxonBase taxonbase, Integer pageSize, Integer pageNumber, List<String> propertyPaths);
+
+       /**
+     * Returns a count of derivation events that have involved creating new DerivedUnits from this occurence
+     *
+        * @param occurence the occurence that was a source of these derivation events
+     * @return a count of derivation events
+     */
+    public int countDerivationEvents(SpecimenOrObservationBase occurence);
+
+    /**
+     * Returns a list of derivation events that have involved creating new DerivedUnits from this occurence
+     *
+        * @param occurence the occurence that was a source of these derivation events
+        * @param pageSize The maximum number of derivation events returned (can be null for all related derivation events)
+        * @param pageNumber The offset (in pageSize chunks) from the start of the result set (0 - based)
+        * @param propertyPaths properties to initialize - see {@link IBeanInitializer#initialize(Object, List)}
+     * @return a List of derivation events
+     */
+       public List<DerivationEvent> getDerivationEvents(SpecimenOrObservationBase occurence, Integer pageSize, Integer pageNumber, List<String> propertyPaths);
+
+    /**
+     * Retrieves the {@link UUID} and the string representation (title cache) of all
+     * {@link FieldUnit}s found in the data base.
+     * @return a list of {@link UuidAndTitleCache}
+     */
+       public List<UuidAndTitleCache<FieldUnit>> getFieldUnitUuidAndTitleCache();
+
+    /**
+     * Retrieves the {@link UUID} and the string representation (title cache) of all
+     * {@link DerivedUnit}s found in the data base.
+     * @return a list of {@link UuidAndTitleCache}
+     */
+       public List<UuidAndTitleCache<DerivedUnit>> getDerivedUnitUuidAndTitleCache();
+
+       /**
+        * Lists all instances of {@link SpecimenOrObservationBase} which are associated with the <code>taxon</code> specified as parameter.
+        * SpecimenOrObservationBase instances can be associated to taxa in multiple ways, all these possible relations are taken into account:
+        * <ul>
+        * <li>The {@link IndividualsAssociation} elements in a {@link TaxonDescription} contain {@link DerivedUnit}s</li>
+        * <li>{@link SpecimenTypeDesignation}s may be associated with any {@link HomotypicalGroup} related to the specific {@link Taxon}.</li>
+        * <li>A {@link Taxon} may be referenced by the {@link DeterminationEvent} of the {@link SpecimenOrObservationBase}</li>
+        * </ul>
+        *
+        * @param <T>
+        * @param type
+        * @param associatedTaxon
+        * @param limit
+        * @param start
+        * @param orderHints
+        * @param propertyPaths
+        * @return
+        */
+       public <T extends SpecimenOrObservationBase> List<T> listByAssociatedTaxon(Class<T> type, Taxon associatedTaxon,
+                       Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+
+    /**
+     * Retrieves all {@link IndividualsAssociation} with the given specimen.<br>
+     * @param specimen the specimen for which the associations are retrieved
+     * @param limit
+     * @param start
+     * @param orderHints
+     * @param propertyPaths
+     * @return collection of all associations
+     */
+       public Collection<IndividualsAssociation> listIndividualsAssociations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+
+    /**
+     * Retrieves all {@link SpecimenTypeDesignation}s which have the given specimen as a type specimen.
+     * @param specimen the type specimen
+     * @param limit
+     * @param start
+     * @param orderHints
+     * @param propertyPaths
+     * @return collection of all designations with the given type specimen
+     */
+    public Collection<SpecimenTypeDesignation> listTypeDesignations(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+
+    /**
+     * Retrieves all {@link DescriptionBase}s that have the given specimen set as described specimen.
+     * @param specimen the described specimen
+     * @param limit
+     * @param start
+     * @param orderHints
+     * @param propertyPaths
+     * @return collection of all descriptions with the given described specimen
+     */
+    public Collection<DescriptionBase<?>> listDescriptionsWithDescriptionSpecimen(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+
+    /**
+     * Retrieves all {@link SpecimenOrObservationBase}s that have the given {@link SpecimenOrObservationType}.
+     * @param type
+     * @param limit
+     * @param start
+     * @param orderHints
+     * @param propertyPaths
+     * @return collection of specimen with the given type
+     */
+    public Collection<SpecimenOrObservationBase> listBySpecimenOrObservationType(SpecimenOrObservationType type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);
+}