/**\r
* Copyright (C) 2008 EDIT\r
-* European Distributed Institute of Taxonomy \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 org.springframework.beans.factory.annotation.Autowired;\r
import org.springframework.stereotype.Repository;\r
\r
-import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\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.name.TypeDesignationBase;\r
import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;\r
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
-import eu.etaxonomy.cdm.model.occurrence.DerivedUnitBase;\r
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
-import eu.etaxonomy.cdm.model.occurrence.FieldObservation;\r
-import eu.etaxonomy.cdm.model.occurrence.Fossil;\r
-import eu.etaxonomy.cdm.model.occurrence.LivingBeing;\r
-import eu.etaxonomy.cdm.model.occurrence.Observation;\r
-import eu.etaxonomy.cdm.model.occurrence.Specimen;\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.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
*/\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] = FieldObservation.class;\r
- indexedClasses[1] = DerivedUnit.class;\r
- indexedClasses[2] = LivingBeing.class;\r
- indexedClasses[3] = Observation.class;\r
- indexedClasses[4] = Specimen.class;\r
- indexedClasses[5] = DnaSample.class;\r
- indexedClasses[6] = Fossil.class;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#countDerivationEvents(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)\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
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#countDeterminations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.taxon.TaxonBase)\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
+\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
+ criteria.add(Restrictions.eq("identifiedUnit",occurrence));\r
}\r
- \r
+\r
if(taxonBase != null) {\r
- criteria.add(Restrictions.eq("taxon",taxonBase));\r
+ criteria.add(Restrictions.eq("taxon",taxonBase));\r
}\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
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#countMedia(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)\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
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getDerivationEvents(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, java.lang.Integer, java.lang.Integer, java.util.List)\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 = (List<DerivationEvent>)query.list();\r
- defaultBeanInitializer.initializeAll(result, propertyPaths);\r
- return result;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getDeterminations(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)\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
+ 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
- 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 = (List<DeterminationEvent>)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 = (List<DeterminationEvent>)query.getResultList();\r
- defaultBeanInitializer.initializeAll(result, propertyPaths); \r
- return result;\r
- }\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getMedia(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase, java.lang.Integer, java.lang.Integer, java.util.List)\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 = (List<Media>)query.list();\r
- defaultBeanInitializer.initializeAll(results, propertyPaths); \r
- return results;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase#rebuildIndex()\r
- */\r
- @Override\r
- public void rebuildIndex() {\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 DerivedUnitBase) {\r
- DerivedUnitBase derivedUnit = (DerivedUnitBase) 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(FieldObservation.class)) {\r
- FieldObservation fieldObservation = original.deproxy(original, FieldObservation.class);\r
- Hibernate.initialize(fieldObservation.getGatheringEvent());\r
- if(fieldObservation.getGatheringEvent() != null) {\r
- Hibernate.initialize(fieldObservation.getGatheringEvent().getActor());\r
- }\r
- }\r
- }\r
- fullTextSession.index(occurrence);\r
- }\r
- fullTextSession.flushToIndexes();\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#count(java.lang.Class, eu.etaxonomy.cdm.model.taxon.TaxonBase)\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
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#list(java.lang.Class, eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\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 = (List<SpecimenOrObservationBase>)criteria.list();\r
- defaultBeanInitializer.initializeAll(results, propertyPaths);\r
- return results; \r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getDerivedUnitBaseUuidAndTitleCache()\r
- */\r
- @Override\r
- public List<UuidAndTitleCache<DerivedUnitBase>> getDerivedUnitBaseUuidAndTitleCache() {\r
- List<UuidAndTitleCache<DerivedUnitBase>> list = new ArrayList<UuidAndTitleCache<DerivedUnitBase>>();\r
- Session session = getSession();\r
- \r
- Query query = session.createQuery("select uuid, titleCache from " + type.getSimpleName() + " where NOT dtype = " + FieldObservation.class.getSimpleName());\r
- \r
- List<Object[]> result = query.list();\r
- \r
- for(Object[] object : result){\r
- list.add(new UuidAndTitleCache<DerivedUnitBase>(DerivedUnitBase.class, (UUID) object[0], (String) object[1]));\r
- }\r
- \r
- return list;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#getFieldObservationUuidAndTitleCache()\r
- */\r
- @Override\r
- public List<UuidAndTitleCache<FieldObservation>> getFieldObservationUuidAndTitleCache() {\r
- List<UuidAndTitleCache<FieldObservation>> list = new ArrayList<UuidAndTitleCache<FieldObservation>>();\r
- Session session = getSession();\r
- \r
- Query query = session.createQuery("select uuid, titleCache from " + type.getSimpleName() + " where dtype = " + FieldObservation.class.getSimpleName());\r
- \r
- List<Object[]> result = query.list();\r
- \r
- for(Object[] object : result){\r
- list.add(new UuidAndTitleCache<FieldObservation>(FieldObservation.class, (UUID) object[0], (String) object[1]));\r
- }\r
- \r
- return list;\r
- }\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao#listByAnyAssociation(java.lang.Class, eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\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 DerivedUnitBases \r
- List<IndividualsAssociation> byIndividualsAssociation = descriptionDao.getDescriptionElementForTaxon(\r
- associatedTaxon, 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 = (List<T>) query.list();\r
- defaultBeanInitializer.initializeAll(results, propertyPaths);\r
- return results;\r
- }\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
+ Set<SpecimenOrObservationType> typeAndSubtypes = new HashSet<SpecimenOrObservationType>();\r
+ if(recordBasis==null){\r
+ //add all types\r
+ SpecimenOrObservationType[] values = SpecimenOrObservationType.values();\r
+ for (SpecimenOrObservationType specimenOrObservationType : values) {\r
+ typeAndSubtypes.add(specimenOrObservationType);\r
+ }\r
+ }\r
+ else{\r
+ typeAndSubtypes = recordBasis.getGeneralizationOf(true);\r
+ typeAndSubtypes.add(recordBasis);\r
+ }\r
+ criteria.add(Restrictions.in("recordBasis", typeAndSubtypes));\r
+\r
+ //taxon associations\r
+ if(associatedTaxon!=null){\r
+ List<UUID> associatedTaxonUuids = new ArrayList<UUID>();\r
+ List<? extends SpecimenOrObservationBase> associatedTaxaList = listByAssociatedTaxon(clazz, 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<SpecimenOrObservationBase> 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
}
\ No newline at end of file