Merge branch 'develop' of ssh://dev.e-taxonomy.eu/var/git/cdmlib into develop
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / NameServiceImpl.java
index fde92df8144bc9c7b2324dc3ac3cce3675fcc142..8f671809852afe20582fbeedaca4e641cc8117fb 100644 (file)
@@ -11,6 +11,7 @@ package eu.etaxonomy.cdm.api.service;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -36,6 +37,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;
 import eu.etaxonomy.cdm.api.service.config.NameDeletionConfigurator;
+import eu.etaxonomy.cdm.api.service.dto.TypeDesignationStatusFilter;
 import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
 import eu.etaxonomy.cdm.api.service.pager.Pager;
 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
@@ -57,6 +59,7 @@ import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.ReferencedEntityBase;
 import eu.etaxonomy.cdm.model.common.RelationshipBase;
 import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
+import eu.etaxonomy.cdm.model.common.SourcedEntityBase;
 import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
 import eu.etaxonomy.cdm.model.name.HybridRelationship;
@@ -68,19 +71,27 @@ import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
 import eu.etaxonomy.cdm.model.name.Rank;
 import eu.etaxonomy.cdm.model.name.Registration;
+import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
 import eu.etaxonomy.cdm.model.name.TaxonName;
 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
+import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
+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.persistence.dao.common.ICdmGenericDao;
-import eu.etaxonomy.cdm.persistence.dao.common.IOrderedTermVocabularyDao;
 import eu.etaxonomy.cdm.persistence.dao.common.IReferencedEntityDao;
-import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
+import eu.etaxonomy.cdm.persistence.dao.common.ISourcedEntityDao;
+import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
+import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
 import eu.etaxonomy.cdm.persistence.dao.name.IHomotypicalGroupDao;
 import eu.etaxonomy.cdm.persistence.dao.name.INomenclaturalStatusDao;
 import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;
 import eu.etaxonomy.cdm.persistence.dao.name.ITypeDesignationDao;
+import eu.etaxonomy.cdm.persistence.dao.term.IOrderedTermVocabularyDao;
+import eu.etaxonomy.cdm.persistence.dao.term.ITermVocabularyDao;
 import eu.etaxonomy.cdm.persistence.dto.TaxonNameParts;
 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
 import eu.etaxonomy.cdm.persistence.query.MatchMode;
@@ -102,9 +113,16 @@ public class NameServiceImpl
     @Autowired
     protected IOrderedTermVocabularyDao orderedVocabularyDao;
     @Autowired
+    protected IOccurrenceService occurrenceService;
+    @Autowired
+    protected ICollectionService collectionService;
+    @Autowired
     @Qualifier("refEntDao")
     protected IReferencedEntityDao<ReferencedEntityBase> referencedEntityDao;
     @Autowired
+    @Qualifier("sourcedEntityDao")
+    protected ISourcedEntityDao<SourcedEntityBase<?>> sourcedEntityDao;
+    @Autowired
     private INomenclaturalStatusDao nomStatusDao;
     @Autowired
     private ITypeDesignationDao typeDesignationDao;
@@ -114,6 +132,9 @@ public class NameServiceImpl
     private ICdmGenericDao genericDao;
     @Autowired
     private ILuceneIndexToolProvider luceneIndexToolProvider;
+    @Autowired
+    // @Qualifier("defaultBeanInitializer")
+    protected IBeanInitializer defaultBeanInitializer;
 
     /**
      * Constructor
@@ -122,7 +143,6 @@ public class NameServiceImpl
 
 //********************* METHODS ****************************************************************//
 
-
     @Override
     @Transactional(readOnly = false)
     public DeleteResult delete(UUID nameUUID){
@@ -192,11 +212,46 @@ public class NameServiceImpl
         return delete(name, config);
     }
 
+    @Override
+    @Transactional(readOnly = false)
+    public UpdateResult cloneTypeDesignation(UUID nameUuid, SpecimenTypeDesignation baseDesignation,
+            String accessionNumber, String barcode, String catalogNumber,
+            UUID collectionUuid, SpecimenTypeDesignationStatus typeStatus){
+        UpdateResult result = new UpdateResult();
+
+        DerivedUnit baseSpecimen = HibernateProxyHelper.deproxy(occurrenceService.load(baseDesignation.getTypeSpecimen().getUuid(), Arrays.asList("collection")), DerivedUnit.class);
+        DerivedUnit duplicate = DerivedUnit.NewInstance(baseSpecimen.getRecordBasis());
+        DerivationEvent derivedFrom = baseSpecimen.getDerivedFrom();
+        Collection<FieldUnit> fieldUnits = occurrenceService.findFieldUnits(baseSpecimen.getUuid(), null);
+        if(fieldUnits.size()!=1){
+            result.addException(new Exception("More than one or no field unit found for specimen"));
+            result.setError();
+            return result;
+        }
+        for (SpecimenOrObservationBase original : derivedFrom.getOriginals()) {
+            DerivationEvent.NewSimpleInstance(original, duplicate, derivedFrom.getType());
+        }
+        duplicate.setAccessionNumber(accessionNumber);
+        duplicate.setBarcode(barcode);
+        duplicate.setCatalogNumber(catalogNumber);
+        duplicate.setCollection(collectionService.load(collectionUuid));
+        SpecimenTypeDesignation typeDesignation = SpecimenTypeDesignation.NewInstance();
+        typeDesignation.setTypeSpecimen(duplicate);
+        typeDesignation.setTypeStatus(typeStatus);
+
+        TaxonName name = load(nameUuid);
+        name.getTypeDesignations().add(typeDesignation);
+
+        result.setCdmEntity(typeDesignation);
+        result.addUpdatedObject(name);
+        return result;
+    }
+
     @Override
     @Transactional
-    public DeleteResult deleteTypeDesignation(TaxonName name, TypeDesignationBase typeDesignation){
+    public DeleteResult deleteTypeDesignation(TaxonName name, TypeDesignationBase<?> typeDesignation){
        if(typeDesignation != null && typeDesignation .isPersited()){
-               typeDesignation = HibernateProxyHelper.deproxy(referencedEntityDao.load(typeDesignation.getUuid()), TypeDesignationBase.class);
+               typeDesignation = HibernateProxyHelper.deproxy(sourcedEntityDao.load(typeDesignation.getUuid()), TypeDesignationBase.class);
        }
 
         DeleteResult result = new DeleteResult();
@@ -206,16 +261,17 @@ public class NameServiceImpl
         }else if (name != null && typeDesignation != null){
             removeSingleDesignation(name, typeDesignation);
         }else if (name != null){
-            Set<TypeDesignationBase<?>> designationSet = new HashSet<>(name.getTypeDesignations());
-            for (Object o : designationSet){
-                TypeDesignationBase<?> desig = CdmBase.deproxy(o, TypeDesignationBase.class);
+            @SuppressWarnings("rawtypes")
+            Set<TypeDesignationBase<?>> designationSet = new HashSet(name.getTypeDesignations());
+            for (TypeDesignationBase<?> desig : designationSet){
+                desig = CdmBase.deproxy(desig);
                 removeSingleDesignation(name, desig);
             }
         }else if (typeDesignation != null){
             @SuppressWarnings("unchecked")
-            Set<TaxonName> nameSet = new HashSet<>(typeDesignation.getTypifiedNames());
-            for (Object o : nameSet){
-                TaxonName singleName = CdmBase.deproxy(o, TaxonName.class);
+            Set<TaxonName> nameSet = new HashSet(typeDesignation.getTypifiedNames());
+            for (TaxonName singleName : nameSet){
+                singleName = CdmBase.deproxy(singleName);
                 removeSingleDesignation(singleName, typeDesignation);
             }
         }
@@ -229,7 +285,7 @@ public class NameServiceImpl
     @Transactional(readOnly = false)
     public DeleteResult deleteTypeDesignation(UUID nameUuid, UUID typeDesignationUuid){
         TaxonName nameBase = load(nameUuid);
-        TypeDesignationBase<?> typeDesignation = HibernateProxyHelper.deproxy(referencedEntityDao.load(typeDesignationUuid), TypeDesignationBase.class);
+        TypeDesignationBase<?> typeDesignation = HibernateProxyHelper.deproxy(sourcedEntityDao.load(typeDesignationUuid), TypeDesignationBase.class);
         return deleteTypeDesignation(nameBase, typeDesignation);
     }
 
@@ -238,7 +294,8 @@ public class NameServiceImpl
      * @param typeDesignation
      */
     @Transactional
-    private void removeSingleDesignation(TaxonName name, TypeDesignationBase typeDesignation) {
+    private void removeSingleDesignation(TaxonName name, TypeDesignationBase<?> typeDesignation) {
+
         name.removeTypeDesignation(typeDesignation);
         if (typeDesignation.getTypifiedNames().isEmpty()){
             typeDesignation.removeType();
@@ -249,6 +306,7 @@ public class NameServiceImpl
                     }
                 }
             }
+
             typeDesignationDao.delete(typeDesignation);
 
         }
@@ -320,7 +378,6 @@ public class NameServiceImpl
         return result;
     }
 
-
     /**
      * TODO candidate for harmonization
      * new name saveHomotypicalGroups
@@ -341,22 +398,23 @@ public class NameServiceImpl
      */
     @Override
     public List<TaxonName> findNamesByNameCache(String nameCache, MatchMode matchMode, List<String> propertyPaths){
-        List result = dao.findByName(false, nameCache, matchMode, null, null, null , propertyPaths);
+        List<TaxonName> result = dao.findByName(false, nameCache, matchMode, null, null, null , propertyPaths);
         return result;
     }
 
     @Override
     public Pager<TaxonNameParts> findTaxonNameParts(Optional<String> genusOrUninomial,
             Optional<String> infraGenericEpithet, Optional<String> specificEpithet,
-            Optional<String> infraSpecificEpithet, Rank rank, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints) {
+            Optional<String> infraSpecificEpithet, Rank rank, Set<UUID> excludedNamesUuids,
+            Integer pageSize, Integer pageIndex, List<OrderHint> orderHints) {
 
 
-        long count = dao.countTaxonNameParts(genusOrUninomial, infraGenericEpithet, specificEpithet, infraGenericEpithet, rank);
+        long count = dao.countTaxonNameParts(genusOrUninomial, infraGenericEpithet, specificEpithet, infraGenericEpithet, rank, excludedNamesUuids);
 
         List<TaxonNameParts> results;
         if(AbstractPagerImpl.hasResultsInRange(count, pageIndex, pageSize)){
             results = dao.findTaxonNameParts(genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet,
-                    rank,
+                    rank, excludedNamesUuids,
                     pageSize, pageIndex, orderHints);
         } else {
             results = new ArrayList<>();
@@ -378,6 +436,7 @@ public class NameServiceImpl
                 filter.specificEpithet(namePartQueryString),
                 filter.infraspecificEpithet(namePartQueryString),
                 filter.getRank(),
+                filter.getExludedNamesUuids(),
                 pageSize, pageIndex, orderHints);
     }
 
@@ -397,20 +456,10 @@ public class NameServiceImpl
      */
     @Override
     @Transactional(readOnly = false)
-    public Map<UUID, TypeDesignationBase> saveTypeDesignationAll(Collection<TypeDesignationBase> typeDesignationCollection){
+    public Map<UUID, TypeDesignationBase<?>> saveTypeDesignationAll(Collection<TypeDesignationBase<?>> typeDesignationCollection){
         return typeDesignationDao.saveAll(typeDesignationCollection);
     }
 
-    /**
-     * TODO candidate for harmonization
-     * new name saveReferencedEntities
-     */
-    @Override
-    @Transactional(readOnly = false)
-    public Map<UUID, ReferencedEntityBase> saveReferencedEntitiesAll(Collection<ReferencedEntityBase> referencedEntityCollection){
-        return referencedEntityDao.saveAll(referencedEntityCollection);
-    }
-
     /**
      * TODO candidate for harmonization
      * new name getNomenclaturalStatus
@@ -420,22 +469,27 @@ public class NameServiceImpl
         return nomStatusDao.list(limit, start);
     }
 
+    @Override
+    public NomenclaturalStatus loadNomenclaturalStatus(UUID uuid,  List<String> propertyPaths){
+        return nomStatusDao.load(uuid, propertyPaths);
+    }
+
     /**
      * TODO candidate for harmonization
      * new name getTypeDesignations
      */
     @Override
-    public List<TypeDesignationBase> getAllTypeDesignations(int limit, int start){
+    public List<TypeDesignationBase<?>> getAllTypeDesignations(int limit, int start){
         return typeDesignationDao.getAllTypeDesignations(limit, start);
     }
 
     @Override
-    public TypeDesignationBase loadTypeDesignation(int id, List<String> propertyPaths){
+    public TypeDesignationBase<?> loadTypeDesignation(int id, List<String> propertyPaths){
         return typeDesignationDao.load(id, propertyPaths);
     }
 
     @Override
-    public TypeDesignationBase loadTypeDesignation(UUID uuid, List<String> propertyPaths){
+    public TypeDesignationBase<?> loadTypeDesignation(UUID uuid, List<String> propertyPaths){
         return typeDesignationDao.load(uuid, propertyPaths);
     }
 
@@ -791,10 +845,18 @@ public class NameServiceImpl
         if(AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)) {
             results = dao.getTypeDesignations(name, null, status, pageSize, pageNumber, propertyPaths);
         }
-
         return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
     }
 
+    @Override
+    public List<TypeDesignationBase> getTypeDesignationsInHomotypicalGroup(UUID nameUuid, Integer pageSize,
+            Integer pageNumber, List<String> propertyPaths){
+        TaxonName name = load(nameUuid, Arrays.asList("nomenclaturalReference.authorship"));
+        Set<TypeDesignationBase<?>> typeDesignations = name.getHomotypicalGroup().getTypeDesignations();
+        List<TypeDesignationBase> result = defaultBeanInitializer.initializeAll(new ArrayList(typeDesignations), propertyPaths);
+        return result;
+    }
+
     /**
      * FIXME Candidate for harmonization
      * rename search
@@ -818,7 +880,8 @@ public class NameServiceImpl
     }
 
     @Override
-    public Pager<TaxonName> findByName(Class<? extends TaxonName> clazz, String queryString, MatchMode matchmode, List<Criterion> criteria, Integer pageSize,Integer pageNumber, List<OrderHint> orderHints,List<String> propertyPaths) {
+    public Pager<TaxonName> findByName(Class<TaxonName> clazz, String queryString, MatchMode matchmode, List<Criterion> criteria,
+            Integer pageSize,Integer pageNumber, List<OrderHint> orderHints,List<String> propertyPaths) {
          Long numberOfResults = dao.countByName(clazz, queryString, matchmode, criteria);
 
          List<TaxonName> results = new ArrayList<>();
@@ -836,28 +899,14 @@ public class NameServiceImpl
 
     @Override
     @Transactional(readOnly = false)
-    public void updateTitleCache(Class<? extends TaxonName> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<TaxonName> cacheStrategy, IProgressMonitor monitor) {
+    public UpdateResult updateCaches(Class<? extends TaxonName> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<TaxonName> cacheStrategy, IProgressMonitor monitor) {
         if (clazz == null){
             clazz = TaxonName.class;
         }
-        super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
+        return super.updateCachesImpl(clazz, stepSize, cacheStrategy, monitor);
     }
 
 
-    @Override
-    protected void setOtherCachesNull(TaxonName name) {
-         if (! name.isProtectedNameCache()){
-             name.setNameCache(null, false);
-        }
-        if (! name.isProtectedAuthorshipCache()){
-            name.setAuthorshipCache(null, false);
-        }
-        if (! name.isProtectedFullTitleCache()){
-            name.setFullTitleCache(null, false);
-        }
-
-    }
-
     @Override
     public List<TaggedText> getTaggedName(UUID uuid) {
         TaxonName taxonName = dao.load(uuid);
@@ -993,4 +1042,48 @@ public class NameServiceImpl
 
     }
 
+    @Override
+    public List<TypeDesignationStatusBase> getTypeDesignationStatusInUse(){
+        return typeDesignationDao.getTypeDesignationStatusInUse();
+    }
+
+    @Override
+    public Collection<TypeDesignationStatusFilter> getTypeDesignationStatusFilterTerms(List<Language> preferredLanguages){
+        List<TypeDesignationStatusBase> termList = typeDesignationDao.getTypeDesignationStatusInUse();
+        Map<String, TypeDesignationStatusFilter>  filterMap = new HashMap<>();
+        for(TypeDesignationStatusBase term : termList){
+            TypeDesignationStatusFilter filter = new TypeDesignationStatusFilter(term, preferredLanguages, true);
+            String key = filter.getKey();
+            if(filterMap.containsKey(key)){
+                filterMap.get(key).addStatus(term);
+            } else {
+                filterMap.put(key, filter);
+            }
+        }
+        return filterMap.values();
+    }
+
+    @Override
+    public <S extends TaxonName> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize,
+            Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths) {
+        return page(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths, INCLUDE_UNPUBLISHED);
+    }
+
+    @Override
+    public <S extends TaxonName> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize,
+            Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths, boolean includeUnpublished) {
+
+        List<S> records;
+        long resultSize = dao.count(clazz, restrictions);
+        if(AbstractPagerImpl.hasResultsInRange(resultSize, pageIndex, pageSize)){
+            records = dao.list(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths, includeUnpublished);
+        } else {
+            records = new ArrayList<>();
+        }
+        Pager<S> pager = new DefaultPagerImpl<>(pageIndex, resultSize, pageSize, records);
+        return pager;
+    }
+
+
+
 }