2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.api
.service
;
11 import java
.io
.IOException
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Arrays
;
14 import java
.util
.Collection
;
15 import java
.util
.HashMap
;
16 import java
.util
.List
;
18 import java
.util
.Optional
;
20 import java
.util
.UUID
;
21 import java
.util
.stream
.Collectors
;
23 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
24 import org
.springframework
.security
.core
.Authentication
;
25 import org
.springframework
.stereotype
.Service
;
26 import org
.springframework
.transaction
.annotation
.Transactional
;
28 import eu
.etaxonomy
.cdm
.api
.service
.idminter
.IdentifierMinter
.Identifier
;
29 import eu
.etaxonomy
.cdm
.api
.service
.idminter
.RegistrationIdentifierMinter
;
30 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
31 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.AbstractPagerImpl
;
32 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
33 import eu
.etaxonomy
.cdm
.api
.service
.taxonGraph
.ITaxonGraphService
;
34 import eu
.etaxonomy
.cdm
.api
.util
.UserHelper
;
35 import eu
.etaxonomy
.cdm
.model
.name
.Registration
;
36 import eu
.etaxonomy
.cdm
.model
.name
.RegistrationStatus
;
37 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
38 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
39 import eu
.etaxonomy
.cdm
.model
.permission
.Operation
;
40 import eu
.etaxonomy
.cdm
.model
.permission
.User
;
41 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
42 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.Restriction
;
43 import eu
.etaxonomy
.cdm
.persistence
.dao
.name
.IRegistrationDao
;
44 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
45 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
48 * @author a.kohlbecker
52 @Transactional(readOnly
= true)
53 public class RegistrationServiceImpl
extends AnnotatableServiceBase
<Registration
, IRegistrationDao
>
54 implements IRegistrationService
{
58 protected void setDao(IRegistrationDao dao
) {
62 @Autowired(required
=false)
63 private RegistrationIdentifierMinter minter
;
66 private UserHelper userHelper
;
69 private INameService nameService
;
72 private ITaxonGraphService taxonGraphService
;
75 @Transactional(readOnly
= true)
76 public Pager
<Registration
> page(Optional
<Reference
> reference
, Collection
<RegistrationStatus
> includedStatus
,
77 Integer pageSize
, Integer pageIndex
, List
<String
> propertyPaths
) {
79 if( !userHelper
.userIsAutheticated() || userHelper
.userIsAnnonymous() ) {
80 includedStatus
= Arrays
.asList(RegistrationStatus
.PUBLISHED
);
83 long numberOfResults
= dao
.count(reference
, includedStatus
);
85 List
<Registration
> results
= new ArrayList
<>();
86 Integer
[] limitStart
= AbstractPagerImpl
.limitStartforRange(numberOfResults
, pageIndex
, pageSize
);
87 if(limitStart
!= null) {
88 results
= dao
.list(reference
, includedStatus
, limitStart
[0], limitStart
[1], propertyPaths
);
91 return new DefaultPagerImpl
<>(pageIndex
, numberOfResults
, pageSize
, results
);
95 @Transactional(readOnly
= true)
96 public Pager
<Registration
> page(UUID submitterUuid
, Collection
<RegistrationStatus
> includedStatus
,
97 String identifierFilterPattern
, String taxonNameFilterPattern
, String referenceFilterPattern
,
98 Collection
<UUID
> typeDesignationStatusUuids
, Integer pageSize
, Integer pageIndex
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
100 if( !userHelper
.userIsAutheticated() || userHelper
.userIsAnnonymous() ) {
101 includedStatus
= Arrays
.asList(RegistrationStatus
.PUBLISHED
);
104 // LogUtils.setLevel("org.hibernate.SQL", Level.TRACE);
105 long numberOfResults
= dao
.count(submitterUuid
, includedStatus
, identifierFilterPattern
, taxonNameFilterPattern
, referenceFilterPattern
, typeDesignationStatusUuids
);
106 // LogUtils.setLevel("org.hibernate.SQL", Level.WARN);
108 List
<Registration
> results
= new ArrayList
<>();
109 if(pageIndex
== null){
112 Integer
[] limitStart
= AbstractPagerImpl
.limitStartforRange(numberOfResults
, pageIndex
, pageSize
);
113 if(limitStart
!= null) {
114 results
= dao
.list(submitterUuid
, includedStatus
, identifierFilterPattern
, taxonNameFilterPattern
, referenceFilterPattern
, typeDesignationStatusUuids
,
115 limitStart
[0], limitStart
[1], orderHints
, propertyPaths
);
118 return new DefaultPagerImpl
<>(pageIndex
, numberOfResults
, pageSize
, results
);
122 @Transactional(readOnly
= true)
123 public Pager
<Registration
> pageTaxomicInclusion(UUID submitterUuid
, Collection
<RegistrationStatus
> includedStatus
,
124 String taxonNameFilterPattern
, MatchMode matchMode
,
125 Integer pageSize
, Integer pageIndex
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
127 List
<TaxonName
> includedNames
= taxonGraphService
.listIncludedNames(taxonNameFilterPattern
, matchMode
);
128 Set
<UUID
> includedNamesUuids
= includedNames
.stream().map(TaxonName
::getUuid
).collect(Collectors
.toSet());
130 if(includedNames
.size() > 0){
131 return page(submitterUuid
, includedStatus
, includedNamesUuids
, pageSize
, pageIndex
, orderHints
, propertyPaths
);
133 return new DefaultPagerImpl
<>(pageIndex
, 0l, pageSize
, new ArrayList
<Registration
>());
138 @Transactional(readOnly
= true)
139 public Pager
<Registration
> page(UUID submitterUuid
, Collection
<RegistrationStatus
> includedStatus
,
140 Collection
<UUID
> taxonNameUUIDs
,
141 Integer pageSize
, Integer pageIndex
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
143 if( !userHelper
.userIsAutheticated() || userHelper
.userIsAnnonymous() ) {
144 includedStatus
= Arrays
.asList(RegistrationStatus
.PUBLISHED
);
147 long numberOfResults
= dao
.count(submitterUuid
, includedStatus
, taxonNameUUIDs
);
149 List
<Registration
> results
= new ArrayList
<>();
150 if(pageIndex
== null){
153 Integer
[] limitStart
= AbstractPagerImpl
.limitStartforRange(numberOfResults
, pageIndex
, pageSize
);
154 if(limitStart
!= null) {
155 results
= dao
.list(submitterUuid
, includedStatus
, taxonNameUUIDs
, limitStart
[0], limitStart
[1], orderHints
, propertyPaths
);
158 return new DefaultPagerImpl
<>(pageIndex
, numberOfResults
, pageSize
, results
);
162 @Transactional(readOnly
= true)
163 public Pager
<Registration
> pageByIdentifier(String identifier
, Integer pageIndex
, Integer pageSize
, List
<String
> propertyPaths
) throws IOException
{
165 List
<Restriction
<?
>> restrictions
= new ArrayList
<>();
166 if( !userHelper
.userIsAutheticated() || userHelper
.userIsAnnonymous() ) {
167 restrictions
.add(new Restriction
<>("status", null, RegistrationStatus
.PUBLISHED
));
170 Pager
<Registration
> regPager
= pageByParamWithRestrictions(Registration
.class, "identifier", identifier
, MatchMode
.EXACT
,
171 restrictions
, pageSize
, pageIndex
, null, propertyPaths
);
177 @Transactional(readOnly
= true)
178 public Map
<UUID
, RegistrationStatus
> statusByIdentifier(String identifier
) throws IOException
{
180 Pager
<Registration
> regPager
= pageByParamWithRestrictions(Registration
.class, "identifier", identifier
, MatchMode
.EXACT
,
181 null, null, null, null, Arrays
.asList("status"));
183 Map
<UUID
, RegistrationStatus
> map
= new HashMap
<>();
184 for(Registration reg
: regPager
.getRecords()){
185 map
.put(reg
.getUuid(), reg
.getStatus());
192 public Registration
save(Registration newInstance
) {
193 return assureIsPersisted(newInstance
);
197 public UUID
saveOrUpdate(Registration transientObject
) {
198 transientObject
= assureIsPersisted(transientObject
);
199 return super.saveOrUpdate(transientObject
);
203 public Map
<UUID
, Registration
> save(Collection
<?
extends Registration
> newInstances
) {
204 Map
<UUID
, Registration
> regs
= new HashMap
<>();
205 for(Registration newInstance
: newInstances
) {
206 Registration reg
= save(newInstance
);
207 regs
.put(reg
.getUuid(), reg
);
213 public Map
<UUID
, Registration
> saveOrUpdate(Collection
<Registration
> transientInstances
) {
214 Map
<UUID
, Registration
> regs
= new HashMap
<>();
215 for(Registration transientInstance
: transientInstances
) {
216 UUID uuid
= saveOrUpdate(transientInstance
);
217 regs
.put(uuid
, transientInstance
);
222 // ============= functionality to be moved into a "RegistrationManagerBean" => RegistrationServiceImpl ? ==================
227 * TODO move into RegistrationFactory
229 * @return a new Registration instance with submitter set to the current authentications principal
232 public Registration
newRegistration() {
234 Registration reg
= Registration
.NewInstance(
239 Authentication authentication
= userHelper
.getAuthentication();
240 reg
.setSubmitter((User
)authentication
.getPrincipal());
245 @Transactional(readOnly
=false)
246 public Registration
createRegistrationForName(UUID taxonNameUuid
) {
248 Registration reg
= Registration
.NewInstance(
251 taxonNameUuid
!= null ? nameService
.load(taxonNameUuid
, Arrays
.asList("nomenclaturalSource.citation.inReference")) : null,
254 reg
= assureIsPersisted(reg
);
256 return load(reg
.getUuid(), Arrays
.asList(new String
[]{"blockedBy"}));
260 @Transactional(readOnly
=false)
261 public Registration
assureIsPersisted(Registration reg
) {
263 if(reg
.isPersited()){
268 reg
= super.save(reg
);
269 userHelper
.createAuthorityForCurrentUser(reg
, Operation
.UPDATE
, RegistrationStatus
.PREPARATION
.name());
275 @Transactional(readOnly
=false)
276 public void addTypeDesignation(UUID registrationUUID
, UUID typeDesignationUuid
){
278 // load the typeDesignations with the registration so that typified names can not be twice in detached sessions
279 // otherwise multiple representation problems might occur
280 Registration registration
= load(registrationUUID
, Arrays
.asList("typeDesignations"));
281 if(registration
== null){
282 registration
= newRegistration();
283 registration
= assureIsPersisted(registration
);
285 TypeDesignationBase
<?
> nameTypeDesignation
= nameService
.loadTypeDesignation(typeDesignationUuid
, Arrays
.asList(""));
286 registration
.getTypeDesignations().add(nameTypeDesignation
);
290 @Transactional(readOnly
=false)
291 public void addTypeDesignation(Registration registration
, UUID typeDesignationUuid
){
293 if(registration
== null){
294 registration
= newRegistration();
295 registration
= assureIsPersisted(registration
);
297 if(registration
.isPersited()){
298 // make sure the the typeDesignations are loaded with the registration so that typified names can not be twice in detached sessions
299 // otherwise multiple representation problems might occur
300 registration
.getTypeDesignations();
303 TypeDesignationBase
<?
> nameTypeDesignation
= nameService
.loadTypeDesignation(typeDesignationUuid
, Arrays
.asList(""));
304 registration
.getTypeDesignations().add(nameTypeDesignation
);
308 * Sets the registration identifier and submitter in case the registration is not yet persisted.
311 * The Registration to prepare for saving.
313 private void prepareForSave(Registration reg
) {
315 if(!reg
.isPersited()){
317 Identifier
<String
> identifiers
= minter
.mint();
318 if(identifiers
.getIdentifier() == null){
319 throw new RuntimeException("RegistrationIdentifierMinter configuration incomplete.");
321 reg
.setIdentifier(identifiers
.getIdentifier());
322 reg
.setSpecificIdentifier(identifiers
.getLocalId());
324 Authentication authentication
= userHelper
.getAuthentication();
325 reg
.setSubmitter((User
)authentication
.getPrincipal());
330 public boolean checkRegistrationExistsFor(TaxonName name
) {
332 for(Registration reg
: name
.getRegistrations()){
334 if(minter
.isFromOwnRegistration(reg
.getIdentifier())){
338 return true; // first registrations wins as we can't distinguish them without a minter.
344 // =============================================================================================