ref #7458 implementation of the note field for the TypeSpecimenEditor
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / service / RegistrationWorkingSetService.java
index b611077beb07181ca959d426ec3ca266ea5e2210..93c907e35411496e08cdbf14183d439b7b49bd17 100644 (file)
@@ -9,38 +9,42 @@
 package eu.etaxonomy.cdm.service;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
 
 import org.apache.log4j.Logger;
+import org.hibernate.Hibernate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import eu.etaxonomy.cdm.api.application.CdmRepository;
+import eu.etaxonomy.cdm.api.service.dto.RegistrationDTO;
+import eu.etaxonomy.cdm.api.service.exception.RegistrationValidationException;
 import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
 import eu.etaxonomy.cdm.model.common.User;
 import eu.etaxonomy.cdm.model.name.Registration;
 import eu.etaxonomy.cdm.model.name.RegistrationStatus;
+import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
+import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
+import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
+import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
+import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
 import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.reference.ReferenceType;
+import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
 import eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet;
-import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationDTO;
-import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationValidationException;
 
 /**
  * Provides RegistrationDTOs and RegistrationWorkingsets for Registrations in the database.
- * <p>
- * Can create missing registrations for names which have Extensions of the Type <code>IAPTRegdata.json</code>.
- * See https://dev.e-taxonomy.eu/redmine/issues/6621 for further details.
- * This feature can be activated by by supplying one of the following jvm command line arguments:
- * <ul>
- * <li><code>-DregistrationCreate=iapt</code>: create all iapt Registrations if missing</li>
- * <li><code>-DregistrationWipeout=iapt</code>: remove all iapt Registrations</li>
- * <li><code>-DregistrationWipeout=all</code>: remove all Registrations</li>
- * </ul>
- * The <code>-DregistrationWipeout</code> commands are executed before the <code>-DregistrationCreate</code> and will not change the name and type designations.
  *
  *
  * @author a.kohlbecker
@@ -51,6 +55,80 @@ import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationValidationException
 @Transactional(readOnly=true)
 public class RegistrationWorkingSetService implements IRegistrationWorkingSetService {
 
+    public static final List<String> REGISTRATION_INIT_STRATEGY = Arrays.asList(new String []{
+            "blockedBy",
+            // typeDesignation
+            "typeDesignations.typeStatus",
+            "typeDesignations.typifiedNames.typeDesignations", // important !!
+            "typeDesignations.typeSpecimen",
+            "typeDesignations.typeName.$",
+            "typeDesignations.citation",
+            "typeDesignations.citation.authorship.$",
+            "typeDesignations.annotations", // needed for AnnotatableEntity.clone() in DerivedUnitConverter.copyPropertiesTo
+            "typeDesignations.markers", // needed for AnnotatableEntity.clone() in DerivedUnitConverter.copyPropertiesTo
+            "typeDesignations.registrations", // DerivedUnitConverter.copyPropertiesTo(TARGET n)
+
+            // name
+            "name.$",
+            "name.nomenclaturalReference.authorship.$",
+            "name.nomenclaturalReference.inReference",
+            "name.rank",
+            "name.homotypicalGroup.typifiedNames",
+            "name.status.type",
+            "name.typeDesignations", // important !!"
+            // institution
+            "institution",
+            }
+    );
+
+   /**
+    *
+    */
+   private  List<String> DERIVEDUNIT_INIT_STRATEGY = Arrays.asList(new String[]{
+           "*", // initialize all related entities to allow DerivedUnit conversion, see DerivedUnitConverter.copyPropertiesTo()
+           "derivedFrom.$",
+           "derivedFrom.type", // TODO remove?
+           "derivedFrom.originals.derivationEvents", // important!!
+           "specimenTypeDesignations.typifiedNames.typeDesignations", // important!!
+           "mediaSpecimen.sources"
+   });
+
+   /**
+   *
+   */
+  private List<String> FIELDUNIT_INIT_STRATEGY = Arrays.asList(new String[]{
+          "$",
+          "annotations.*", // * is needed as log as we are using a table in FilterableAnnotationsField
+          "gatheringEvent.$",
+          "gatheringEvent.country",
+          "gatheringEvent.collectingAreas",
+          "gatheringEvent.actor",
+          "derivationEvents.derivatives" // important, otherwise the DerivedUnits are not included into the graph of initialized entities!!!
+  });
+
+  public static final List<String> BLOCKING_REGISTRATION_INIT_STRATEGY = Arrays.asList(new String []{
+
+          "blockedBy.blockedBy",
+          // typeDesignation
+          "blockedBy.typeDesignations.typeStatus",
+//          "typeDesignations.typifiedNames.typeDesignations", // important !!
+//          "typeDesignations.typeSpecimen",
+//          "typeDesignations.typeName.$",
+//          "typeDesignations.citation",
+//          "typeDesignations.citation.authorship.$",
+          // name
+//          "blockedBy.name.$",
+          "blockedBy.name.nomenclaturalReference.authorship",
+          "blockedBy.name.nomenclaturalReference.inReference",
+          "blockedBy.name.rank",
+//          "name.homotypicalGroup.typifiedNames",
+//          "name.status.type",
+//          "name.typeDesignations",
+          // institution
+          "blockedBy.institution",
+          }
+  );
+
     /**
      *
      */
@@ -62,66 +140,155 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
     @Qualifier("cdmRepository")
     private CdmRepository repo;
 
+    @Autowired
+    protected IBeanInitializer defaultBeanInitializer;
+
     public RegistrationWorkingSetService() {
 
     }
 
 
     /**
-     * @param id the CDM Entity id
+     * @param id the Registration entity id
      * @return
      */
     @Override
     public RegistrationDTO loadDtoById(Integer id) {
-        Registration reg = repo.getRegistrationService().find(id);
+        Registration reg = repo.getRegistrationService().load(id, REGISTRATION_INIT_STRATEGY);
+        inititializeSpecimen(reg);
         return new RegistrationDTO(reg);
     }
 
 
+    /**
+     * @param id the Registration entity id
+     * @return
+     */
     @Override
-    public Collection<RegistrationDTO> listDTOs() {
+    public RegistrationDTO loadDtoByUuid(UUID uuid) {
+        Registration reg = repo.getRegistrationService().load(uuid, REGISTRATION_INIT_STRATEGY);
+        inititializeSpecimen(reg);
+        return new RegistrationDTO(reg);
+    }
 
-        List<Registration> regs = repo.getRegistrationService().list(null, PAGE_SIZE, 0, null, null);
 
-        List<RegistrationDTO> dtos = makeDTOs(regs);
-        return dtos;
+    @Override
+    public Pager<RegistrationDTO> pageDTOs(Integer pageSize, Integer pageIndex) {
+
+        return pageDTOs(null, null, null, null, pageSize, pageIndex);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public Collection<RegistrationDTO> listDTOs(User submitter, Collection<RegistrationStatus> includedStatus) {
+    public Pager<RegistrationDTO> pageDTOs(User submitter, Collection<RegistrationStatus> includedStatus,
+            String identifierFilterPattern, String taxonNameFilterPattern,
+            Integer pageSize, Integer pageIndex) {
 
-        Pager<Registration> pager = repo.getRegistrationService().page(submitter, includedStatus, PAGE_SIZE, 0, null, null);
-        return makeDTOs(pager.getRecords());
+        if(pageSize == null){
+            pageSize = PAGE_SIZE;
+        }
+
+        Pager<Registration> pager = repo.getRegistrationService().page(submitter, includedStatus,
+                identifierFilterPattern, taxonNameFilterPattern,
+                PAGE_SIZE, 0, null, REGISTRATION_INIT_STRATEGY);
+        List<Registration> registrations = pager.getRecords();
+        Pager<RegistrationDTO> dtoPager = new DefaultPagerImpl(pager.getCurrentIndex(), pager.getCount(), pager.getPageSize(), makeDTOs(registrations));
+        return dtoPager;
     }
 
+
     /**
      * {@inheritDoc}
      * @throws RegistrationValidationException
      */
     @Override
-    public RegistrationWorkingSet loadWorkingSetByReferenceID(Integer referenceID) throws RegistrationValidationException {
-        Reference reference = repo.getReferenceService().find(referenceID);
-        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(reference), null, null, null, null);
+    public RegistrationWorkingSet loadWorkingSetByReferenceUuid(UUID referenceUuid, boolean resolveSections) throws RegistrationValidationException {
+
+        Reference reference = repo.getReferenceService().find(referenceUuid); // needed to use load to avoid the problem described in #7331
+        if(resolveSections){
+            reference = resolveSection(reference);
+        }
+
+        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(reference), null, null, null, REGISTRATION_INIT_STRATEGY);
+
+        /* for debugging https://dev.e-taxonomy.eu/redmine/issues/7331 */
+        // debugIssue7331(pager);
         return new RegistrationWorkingSet(makeDTOs(pager.getRecords()));
     }
 
+
+    /**
+     * @param reference
+     * @return
+     */
+    protected Reference resolveSection(Reference reference) {
+        repo.getReferenceService().load(reference.getUuid(), Arrays.asList(new String[]{"inReference"})); // needed to avoid the problem described in #7331
+        if(reference.isOfType(ReferenceType.Section) && reference.getInReference() != null) {
+            reference = reference.getInReference();
+        }
+        return reference;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws RegistrationValidationException
+     */
     @Override
-    public RegistrationWorkingSet loadWorkingSetByCitationID(Integer id) throws RegistrationValidationException {
+    public RegistrationWorkingSet loadWorkingSetByReferenceID(Integer referenceID, boolean resolveSections) throws RegistrationValidationException {
+
+        Reference reference = repo.getReferenceService().find(referenceID);
+        if(resolveSections){
+            reference = resolveSection(reference);
+        }
+        repo.getReferenceService().load(reference.getUuid()); // needed to avoid the problem described in #7331
+
+        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(reference), null, null, null, REGISTRATION_INIT_STRATEGY);
+
+        /* for debugging https://dev.e-taxonomy.eu/redmine/issues/7331 */
+        // debugIssue7331(pager);
 
-        Reference ref = repo.getReferenceService().find(id);
-        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(ref), null, null, null, null);
         return new RegistrationWorkingSet(makeDTOs(pager.getRecords()));
     }
 
 
+    /**
+     * @param pager
+     */
+    @SuppressWarnings("unused")
+    private void debugIssue7331(Pager<Registration> pager) {
+        for(Registration reg : pager.getRecords()){
+            if(reg.getName() != null && reg.getName().getNomenclaturalReference().getAuthorship() != null){
+                Reference ref = reg.getName().getNomenclaturalReference();
+                if(!Hibernate.isInitialized(ref.getAuthorship())){
+                    logger.error("UNINITIALIZED");
+                }
+            } else {
+                logger.debug("NO AUTHORS");
+            }
+        }
+    }
+
+    @Override
+    public Set<RegistrationDTO> loadBlockingRegistrations(UUID blockedRegistrationUuid){
+
+        Registration registration = repo.getRegistrationService().load(blockedRegistrationUuid, BLOCKING_REGISTRATION_INIT_STRATEGY);
+        Set<Registration> registrations = registration.getBlockedBy();
+
+        Set<RegistrationDTO> blockingSet = new HashSet<>();
+        for(Registration reg : registrations){
+            blockingSet.add(new RegistrationDTO(reg));
+        }
+        return blockingSet;
+    }
+
     /**
      * @param regs
      * @return
      */
     private List<RegistrationDTO> makeDTOs(List<Registration> regs) {
+        initializeSpecimens(regs);
         List<RegistrationDTO> dtos = new ArrayList<>(regs.size());
         regs.forEach(reg -> {dtos.add(new RegistrationDTO(reg));});
         return dtos;
@@ -129,6 +296,54 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
 
 
 
+    /**
+     * @param regs
+     */
+    private void initializeSpecimens(List<Registration> regs) {
+        for(Registration reg : regs){
+            inititializeSpecimen(reg);
+        }
+
+    }
+
+
+    /**
+     * @param reg
+     */
+    protected void inititializeSpecimen(Registration reg) {
+
+        for(TypeDesignationBase<?> td : reg.getTypeDesignations()){
+            if(td instanceof SpecimenTypeDesignation){
+
+                DerivedUnit derivedUnit = ((SpecimenTypeDesignation) td).getTypeSpecimen();
+                @SuppressWarnings("rawtypes")
+                Set<SpecimenOrObservationBase> sobs = new HashSet<>();
+                sobs.add(HibernateProxyHelper.deproxy(derivedUnit));
+
+                while(sobs != null && !sobs.isEmpty()){
+                    @SuppressWarnings("rawtypes")
+                    Set<SpecimenOrObservationBase> nextSobs = null;
+                    for(@SuppressWarnings("rawtypes") SpecimenOrObservationBase sob : sobs){
+                        sob = HibernateProxyHelper.deproxy(sob);
+                        if(sob == null){
+                            continue;
+                        }
+                        if(DerivedUnit.class.isAssignableFrom(sob.getClass())) {
+                            defaultBeanInitializer.initialize(sob, DERIVEDUNIT_INIT_STRATEGY);
+                            nextSobs = ((DerivedUnit)sob).getOriginals();
+                        }
+                        if(sob instanceof FieldUnit){
+                            defaultBeanInitializer.initialize(sob, FIELDUNIT_INIT_STRATEGY);
+                        }
+                    }
+                    sobs = nextSobs;
+                }
+            }
+        }
+    }
+
+
+