ref #7099 rename model.rights to model.permission
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / registration / RegistrationWorkingSetService.java
index 72143325d27a8df93485fe8c1dab6a57bf1ecc64..a1091181d44fc510381d33f1db95e6723d8b731f 100644 (file)
@@ -20,6 +20,8 @@ import java.util.UUID;
 
 import org.apache.log4j.Logger;
 import org.hibernate.Hibernate;
+import org.joda.time.DateTime;
+import org.joda.time.Partial;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
@@ -31,18 +33,21 @@ import eu.etaxonomy.cdm.api.service.dto.RegistrationWorkingSet;
 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.api.utility.UserHelper;
+import eu.etaxonomy.cdm.database.PermissionDeniedException;
+import eu.etaxonomy.cdm.format.ReferenceEllypsisFormatter;
 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.name.TypeDesignationStatusBase;
 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.permission.CRUD;
 import eu.etaxonomy.cdm.model.reference.Reference;
 import eu.etaxonomy.cdm.model.reference.ReferenceType;
+import eu.etaxonomy.cdm.persistence.dao.initializer.EntityInitStrategy;
 import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
 import eu.etaxonomy.cdm.persistence.query.MatchMode;
 import eu.etaxonomy.cdm.persistence.query.OrderHint;
@@ -60,7 +65,7 @@ import eu.etaxonomy.cdm.persistence.query.OrderHint.SortOrder;
 @Transactional(readOnly=true)
 public class RegistrationWorkingSetService implements IRegistrationWorkingSetService {
 
-    public static final List<String> REGISTRATION_DTO_INIT_STRATEGY = Arrays.asList(new String []{
+    public static final EntityInitStrategy REGISTRATION_DTO_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
             "blockedBy",
             // typeDesignation
             "typeDesignations.typeStatus",
@@ -68,15 +73,13 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
             "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.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.nomenclaturalReference",
             "name.rank",
             "name.homotypicalGroup.typifiedNames",
             "name.status.type",
@@ -84,17 +87,19 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
             // institution
             "institution",
             }
-    );
+            ))
+            .extend("typeDesignations.citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false)
+            .extend("name.nomenclaturalReference", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
 
-    public  List<String> DERIVEDUNIT_INIT_STRATEGY = Arrays.asList(new String[]{
+    public  EntityInitStrategy DERIVEDUNIT_INIT_STRATEGY = new EntityInitStrategy(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",
+           "mediaSpecimen.sources.citation",
            "collection.institute"// see CollectionCaptionGenerator
-   });
+   })).extend("mediaSpecimen.sources.citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
 
    public List<String> FIELDUNIT_INIT_STRATEGY = Arrays.asList(new String[]{
           "$",
@@ -113,19 +118,11 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
           "blockedBy.blockedBy",
           // typeDesignation
           "blockedBy.typeDesignations.typeStatus",
-//          "typeDesignations.typifiedNames.typeDesignations", // important !!
-//          "typeDesignations.typeSpecimen",
-//          "typeDesignations.typeName.$",
-//          "typeDesignations.citation",
-//          "typeDesignations.citation.authorship.$",
-          // name
+//          "typeDesignations.typifiedNames.typeDesignations", // important !?
 //          "blockedBy.name.$",
           "blockedBy.name.nomenclaturalReference.authorship",
           "blockedBy.name.nomenclaturalReference.inReference",
           "blockedBy.name.rank",
-//          "name.homotypicalGroup.typifiedNames",
-//          "name.status.type",
-//          "name.typeDesignations",
           // institution
           "blockedBy.institution",
           }
@@ -142,6 +139,9 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
     @Qualifier("cdmRepository")
     private CdmRepository repo;
 
+    @Autowired
+    private UserHelper userHelper;
+
     @Autowired
     protected IBeanInitializer defaultBeanInitializer;
 
@@ -156,7 +156,7 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
      */
     @Override
     public RegistrationDTO loadDtoById(Integer id) {
-        Registration reg = repo.getRegistrationService().load(id, REGISTRATION_DTO_INIT_STRATEGY);
+        Registration reg = repo.getRegistrationService().load(id, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
         inititializeSpecimen(reg);
         return new RegistrationDTO(reg);
     }
@@ -168,7 +168,7 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
      */
     @Override
     public RegistrationDTO loadDtoByUuid(UUID uuid) {
-        Registration reg = repo.getRegistrationService().load(uuid, REGISTRATION_DTO_INIT_STRATEGY);
+        Registration reg = repo.getRegistrationService().load(uuid, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
         inititializeSpecimen(reg);
         return new RegistrationDTO(reg);
     }
@@ -176,7 +176,7 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
     @Override
     public Pager<RegistrationDTO> pageDTOs(String identifier, Integer pageIndex,  Integer pageSize) throws IOException {
 
-        Pager<Registration> regPager = repo.getRegistrationService().pageByIdentifier(identifier, pageIndex, pageSize, REGISTRATION_DTO_INIT_STRATEGY);
+        Pager<Registration> regPager = repo.getRegistrationService().pageByIdentifier(identifier, pageIndex, pageSize, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
         return convertToDTOPager(regPager);
     }
 
@@ -194,41 +194,36 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
     @Override
     public Pager<RegistrationDTO> pageDTOs(Integer pageSize, Integer pageIndex) {
 
-        return pageDTOs((User)null, null, null, null, null, pageSize, pageIndex, null);
+        return pageDTOs((UUID)null, null, null, null, null, null, pageSize, pageIndex, null);
+
     }
 
     /**
-     * {@inheritDoc}
+     * @param submitterUuid
+     *    Filter by the uuid of the {@link User} associated with the Registration as <code>Registration.submitter</code>
+     * @param includedStatus
+     *    Filter by one or more {@link RegistrationStatus}. Multiple status will be combined with OR. In case the current user
+     *    is not authenticated (i.e. the authentication is anonymous) the includedStatus will be set to {@link RegistrationStatus#PUBLISHED}
+     *    to protect all other Registrations from being undisclosed.
+     * @param identifierFilterPattern
+     *    Filter by the {@link Registration#getIdentifier() Registration.identifier}.
+     *    The method matches Registrations which contain the the passed pattern in the identifier.
+     * @param taxonNameFilterPattern
+     *    The method matches Registrations which contain the the passed pattern in the
+     *    {@link Registration#getName() Registration.name}
+     * @param typeDesignationStatusUuids
+     *    Filter by one or more {@link eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus} or {@link eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus}.
+     *    Multiple status will be combined with OR.
+     * @param pageSize
+     * @param pageIndex
+     * @param orderHints
+     * @return
      */
-    @Override
-    public Pager<RegistrationDTO> pageDTOs(User submitter, Collection<RegistrationStatus> includedStatus,
-            String identifierFilterPattern, String taxonNameFilterPattern, Set<TypeDesignationStatusBase> typeStatusFilter,
-            Integer pageSize, Integer pageIndex, List<OrderHint> orderHints) {
-
-        if(pageSize == null){
-            pageSize = PAGE_SIZE;
-        }
-
-        if(orderHints == null){
-            orderHints = Arrays.asList(new OrderHint("identifier", SortOrder.ASCENDING));
-        }
-
-        Pager<Registration> pager = repo.getRegistrationService().page(submitter, includedStatus, identifierFilterPattern, taxonNameFilterPattern,
-                typeStatusFilter, PAGE_SIZE, pageIndex , orderHints, REGISTRATION_DTO_INIT_STRATEGY);
-
-        Pager<RegistrationDTO> dtoPager = convertToDTOPager(pager);
-        if(logger.isDebugEnabled()){
-            logger.debug(String.format("pageDTOs() pageIndex: $1%d, pageSize: $2%d, includedStatus: $3%s, identifierFilterPattern: $4%s, taxonNameFilterPattern: $5%s, submitter: $6%s",
-                    pageIndex, pageSize, includedStatus, identifierFilterPattern, taxonNameFilterPattern, submitter));
-            logger.debug("pageDTOs() result: " + pager.toString());
-        }
-        return dtoPager;
-    }
 
     @Override
     public Pager<RegistrationDTO> pageDTOs(UUID submitterUuid, Collection<RegistrationStatus> includedStatus, String identifierFilterPattern,
-            String taxonNameFilterPattern, Collection<UUID> typeDesignationStatusUuids, Integer pageSize,
-            Integer pageIndex, List<OrderHint> orderHints){
+            String taxonNameFilterPattern, String referenceFilterPattern, Collection<UUID> typeDesignationStatusUuids,
+            Integer pageSize, Integer pageIndex, List<OrderHint> orderHints){
 
             if(pageSize == null){
                 pageSize = PAGE_SIZE;
@@ -240,7 +235,7 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
 
             Pager<Registration> pager = repo.getRegistrationService().page(submitterUuid, includedStatus,
                     identifierFilterPattern, taxonNameFilterPattern,
-                    typeDesignationStatusUuids, PAGE_SIZE, pageIndex , orderHints, REGISTRATION_DTO_INIT_STRATEGY);
+                    referenceFilterPattern, typeDesignationStatusUuids, PAGE_SIZE , pageIndex, orderHints, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
 
             Pager<RegistrationDTO> dtoPager = convertToDTOPager(pager);
             if(logger.isDebugEnabled()){
@@ -259,7 +254,7 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
 
         Pager<Registration> regPager = repo.getRegistrationService().pageTaxomicInclusion(null, includedStatus,
             taxonNameFilterPattern, matchMode,
-            pageSize, pageIndex, orderHints, REGISTRATION_DTO_INIT_STRATEGY);
+            pageSize, pageIndex, orderHints, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
 
         return convertToDTOPager(regPager);
     }
@@ -270,18 +265,80 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
      * @throws RegistrationValidationException
      */
     @Override
-    public RegistrationWorkingSet loadWorkingSetByReferenceUuid(UUID referenceUuid, boolean resolveSections) throws RegistrationValidationException {
+    public RegistrationWorkingSet loadWorkingSetByReferenceUuid(UUID referenceUuid, boolean resolveSections) throws RegistrationValidationException, PermissionDeniedException {
 
         Reference reference = repo.getReferenceService().load(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_DTO_INIT_STRATEGY);
+        checkPermissions(reference);
+
+        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(reference), null, null, null, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
 
         /* for debugging https://dev.e-taxonomy.eu/redmine/issues/7331 */
         // debugIssue7331(pager);
-        return new RegistrationWorkingSet(makeDTOs(pager.getRecords()));
+        RegistrationWorkingSet registrationWorkingSet;
+        if(pager.getCount() > 0) {
+            registrationWorkingSet = new RegistrationWorkingSet(makeDTOs(pager.getRecords()));
+        } else {
+            registrationWorkingSet = new RegistrationWorkingSet(reference);
+        }
+        return registrationWorkingSet;
+    }
+
+
+    /**
+     * @param reference
+     */
+    private void checkPermissions(Reference reference) throws PermissionDeniedException {
+
+        boolean permissionDenied = isPermissionDenied(reference);
+        if(permissionDenied) {
+            throw new PermissionDeniedException("Access to the workingset is denied for the current user.");
+        }
+    }
+
+
+    /**
+     * @param reference
+     * @return
+     */
+    public boolean isPermissionDenied(Reference reference) {
+        boolean permissionDenied = false;
+        if(!checkReferencePublished(reference)){
+            permissionDenied = !userHelper.userHasPermission(reference, CRUD.UPDATE);
+        }
+        return permissionDenied;
+    }
+
+
+
+    /**
+     * @param reference
+     * @return
+     */
+    public boolean checkReferencePublished(Reference reference) {
+
+        if(reference.getDatePublished() == null){
+            return false;
+        }
+        Partial pubPartial = null;
+        if(reference.getDatePublished().getStart() != null){
+            pubPartial = reference.getDatePublished().getStart();
+        } else {
+            pubPartial = reference.getDatePublished().getEnd();
+        }
+        if(pubPartial == null){
+            return !reference.getDatePublished().getFreeText().isEmpty();
+        }
+
+        DateTime nowLocal = new DateTime();
+        //LocalDateTime nowUTC = nowLocal.withZone(DateTimeZone.UTC).toLocalDateTime();
+
+        DateTime pubDateTime = pubPartial.toDateTime(null);
+        return nowLocal.isAfter(pubDateTime);
+
     }
 
 
@@ -302,15 +359,18 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
      * @throws RegistrationValidationException
      */
     @Override
-    public RegistrationWorkingSet loadWorkingSetByReferenceID(Integer referenceID, boolean resolveSections) throws RegistrationValidationException {
+    public RegistrationWorkingSet loadWorkingSetByReferenceID(Integer referenceID, boolean resolveSections) throws RegistrationValidationException, PermissionDeniedException {
 
         Reference reference = repo.getReferenceService().find(referenceID);
         if(resolveSections){
             reference = resolveSection(reference);
         }
+
+        checkPermissions(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_DTO_INIT_STRATEGY);
+        Pager<Registration> pager = repo.getRegistrationService().page(Optional.of(reference), null, null, null, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
 
         /* for debugging https://dev.e-taxonomy.eu/redmine/issues/7331 */
         // debugIssue7331(pager);
@@ -318,6 +378,18 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
         return new RegistrationWorkingSet(makeDTOs(pager.getRecords()));
     }
 
+    @Override
+    public Pager<RegistrationDTO> pageWorkingSetsByNameUUID(Collection<UUID> taxonNameUuids, Integer pageIndex, Integer pageSize, List<OrderHint> orderHints) throws RegistrationValidationException, PermissionDeniedException {
+
+        if(orderHints == null){
+            orderHints = Arrays.asList(new OrderHint("identifier", SortOrder.ASCENDING));
+        }
+
+        Pager<Registration> pager = repo.getRegistrationService().page((UUID)null, null, taxonNameUuids, pageSize, pageIndex, orderHints, REGISTRATION_DTO_INIT_STRATEGY.getPropertyPaths());
+
+        return new DefaultPagerImpl<RegistrationDTO>(pager.getCurrentIndex(), pager.getCount(), pager.getPageSize(), makeDTOs(pager.getRecords()));
+    }
+
 
     /**
      * @param pager
@@ -353,7 +425,8 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
      * @param regs
      * @return
      */
-    private List<RegistrationDTO> makeDTOs(List<Registration> regs) {
+    @Override
+    public List<RegistrationDTO> makeDTOs(Collection<Registration> regs) {
         initializeSpecimens(regs);
         List<RegistrationDTO> dtos = new ArrayList<>(regs.size());
         regs.forEach(reg -> {dtos.add(new RegistrationDTO(reg));});
@@ -364,7 +437,7 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
     /**
      * @param regs
      */
-    public void initializeSpecimens(List<Registration> regs) {
+    public void initializeSpecimens(Collection<Registration> regs) {
         for(Registration reg : regs){
             inititializeSpecimen(reg);
         }
@@ -394,7 +467,7 @@ public class RegistrationWorkingSetService implements IRegistrationWorkingSetSer
                             continue;
                         }
                         if(DerivedUnit.class.isAssignableFrom(sob.getClass())) {
-                            defaultBeanInitializer.initialize(sob, DERIVEDUNIT_INIT_STRATEGY);
+                            defaultBeanInitializer.initialize(sob, DERIVEDUNIT_INIT_STRATEGY.getPropertyPaths());
                             nextSobs = ((DerivedUnit)sob).getOriginals();
                         }
                         if(sob instanceof FieldUnit){