ref #10222 add agentlink to taxonNodeAgentRelDto
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / RegistrationServiceImpl.java
1 /**
2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9 package eu.etaxonomy.cdm.api.service;
10
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;
17 import java.util.Map;
18 import java.util.Optional;
19 import java.util.Set;
20 import java.util.UUID;
21 import java.util.stream.Collectors;
22
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;
27
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;
46
47 /**
48 * @author a.kohlbecker
49 * @since May 2, 2017
50 */
51 @Service
52 @Transactional(readOnly = true)
53 public class RegistrationServiceImpl extends AnnotatableServiceBase<Registration, IRegistrationDao>
54 implements IRegistrationService {
55
56 @Autowired
57 @Override
58 protected void setDao(IRegistrationDao dao) {
59 this.dao = dao;
60 }
61
62 @Autowired(required=false)
63 private RegistrationIdentifierMinter minter;
64
65 @Autowired
66 private UserHelper userHelper;
67
68 @Autowired
69 private INameService nameService;
70
71 @Autowired
72 private ITaxonGraphService taxonGraphService;
73
74 @Override
75 @Transactional(readOnly = true)
76 public Pager<Registration> page(Optional<Reference> reference, Collection<RegistrationStatus> includedStatus,
77 Integer pageSize, Integer pageIndex, List<String> propertyPaths) {
78
79 if( !userHelper.userIsAutheticated() || userHelper.userIsAnnonymous() ) {
80 includedStatus = Arrays.asList(RegistrationStatus.PUBLISHED);
81 }
82
83 long numberOfResults = dao.count(reference, includedStatus);
84
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);
89 }
90
91 return new DefaultPagerImpl<>(pageIndex, numberOfResults, pageSize, results);
92 }
93
94 @Override
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) {
99
100 if( !userHelper.userIsAutheticated() || userHelper.userIsAnnonymous() ) {
101 includedStatus = Arrays.asList(RegistrationStatus.PUBLISHED);
102 }
103
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);
107
108 List<Registration> results = new ArrayList<>();
109 if(pageIndex == null){
110 pageIndex = 0;
111 }
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);
116 }
117
118 return new DefaultPagerImpl<>(pageIndex, numberOfResults, pageSize, results);
119 }
120
121 @Override
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) {
126
127 List<TaxonName> includedNames = taxonGraphService.listIncludedNames(taxonNameFilterPattern, matchMode);
128 Set<UUID> includedNamesUuids = includedNames.stream().map(TaxonName::getUuid).collect(Collectors.toSet());
129
130 if(includedNames.size() > 0){
131 return page(submitterUuid, includedStatus, includedNamesUuids, pageSize, pageIndex, orderHints, propertyPaths);
132 } else {
133 return new DefaultPagerImpl<>(pageIndex, 0l, pageSize, new ArrayList<Registration>());
134 }
135 }
136
137 @Override
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) {
142
143 if( !userHelper.userIsAutheticated() || userHelper.userIsAnnonymous() ) {
144 includedStatus = Arrays.asList(RegistrationStatus.PUBLISHED);
145 }
146
147 long numberOfResults = dao.count(submitterUuid, includedStatus, taxonNameUUIDs);
148
149 List<Registration> results = new ArrayList<>();
150 if(pageIndex == null){
151 pageIndex = 0;
152 }
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);
156 }
157
158 return new DefaultPagerImpl<>(pageIndex, numberOfResults, pageSize, results);
159 }
160
161 @Override
162 @Transactional(readOnly = true)
163 public Pager<Registration> pageByIdentifier(String identifier, Integer pageIndex, Integer pageSize, List<String> propertyPaths) throws IOException {
164
165 List<Restriction<?>> restrictions = new ArrayList<>();
166 if( !userHelper.userIsAutheticated() || userHelper.userIsAnnonymous() ) {
167 restrictions.add(new Restriction<>("status", null, RegistrationStatus.PUBLISHED));
168 }
169
170 Pager<Registration> regPager = pageByParamWithRestrictions(Registration.class, "identifier", identifier, MatchMode.EXACT,
171 restrictions, pageSize, pageIndex, null, propertyPaths);
172
173 return regPager;
174 }
175
176 @Override
177 @Transactional(readOnly = true)
178 public Map<UUID, RegistrationStatus> statusByIdentifier(String identifier) throws IOException {
179
180 Pager<Registration> regPager = pageByParamWithRestrictions(Registration.class, "identifier", identifier, MatchMode.EXACT,
181 null, null, null, null, Arrays.asList("status"));
182
183 Map<UUID, RegistrationStatus> map = new HashMap<>();
184 for(Registration reg : regPager.getRecords()){
185 map.put(reg.getUuid(), reg.getStatus());
186 }
187
188 return map;
189 }
190
191 @Override
192 public Registration save(Registration newInstance) {
193 return assureIsPersisted(newInstance);
194 }
195
196 @Override
197 public UUID saveOrUpdate(Registration transientObject) {
198 transientObject = assureIsPersisted(transientObject);
199 return super.saveOrUpdate(transientObject);
200 }
201
202 @Override
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);
208 }
209 return regs;
210 }
211
212 @Override
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);
218 }
219 return regs;
220 }
221
222 // ============= functionality to be moved into a "RegistrationManagerBean" => RegistrationServiceImpl ? ==================
223
224
225 /**
226 * Factory Method
227 * TODO move into RegistrationFactory
228 *
229 * @return a new Registration instance with submitter set to the current authentications principal
230 */
231 @Override
232 public Registration newRegistration() {
233
234 Registration reg = Registration.NewInstance(
235 null,
236 null,
237 null,
238 null);
239 Authentication authentication = userHelper.getAuthentication();
240 reg.setSubmitter((User)authentication.getPrincipal());
241 return reg;
242 }
243
244 @Override
245 @Transactional(readOnly=false)
246 public Registration createRegistrationForName(UUID taxonNameUuid) {
247
248 Registration reg = Registration.NewInstance(
249 null,
250 null,
251 taxonNameUuid != null ? nameService.load(taxonNameUuid, Arrays.asList("nomenclaturalSource.citation.inReference")) : null,
252 null);
253
254 reg = assureIsPersisted(reg);
255
256 return load(reg.getUuid(), Arrays.asList(new String []{"blockedBy"}));
257 }
258
259 @Override
260 @Transactional(readOnly=false)
261 public Registration assureIsPersisted(Registration reg) {
262
263 if(reg.isPersited()){
264 return reg;
265 }
266
267 prepareForSave(reg);
268 reg = super.save(reg);
269 userHelper.createAuthorityForCurrentUser(reg, Operation.UPDATE, RegistrationStatus.PREPARATION.name());
270
271 return reg;
272 }
273
274 @Override
275 @Transactional(readOnly=false)
276 public void addTypeDesignation(UUID registrationUUID, UUID typeDesignationUuid){
277
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);
284 }
285 TypeDesignationBase<?> nameTypeDesignation = nameService.loadTypeDesignation(typeDesignationUuid, Arrays.asList(""));
286 registration.getTypeDesignations().add(nameTypeDesignation);
287 }
288
289 @Override
290 @Transactional(readOnly=false)
291 public void addTypeDesignation(Registration registration, UUID typeDesignationUuid){
292
293 if(registration == null){
294 registration = newRegistration();
295 registration = assureIsPersisted(registration);
296 } else {
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();
301 }
302 }
303 TypeDesignationBase<?> nameTypeDesignation = nameService.loadTypeDesignation(typeDesignationUuid, Arrays.asList(""));
304 registration.getTypeDesignations().add(nameTypeDesignation);
305 }
306
307 /**
308 * Sets the registration identifier and submitter in case the registration is not yet persisted.
309 *
310 * @param reg
311 * The Registration to prepare for saving.
312 */
313 private void prepareForSave(Registration reg) {
314
315 if(!reg.isPersited()){
316 if(minter != null){
317 Identifier<String> identifiers = minter.mint();
318 if(identifiers.getIdentifier() == null){
319 throw new RuntimeException("RegistrationIdentifierMinter configuration incomplete.");
320 }
321 reg.setIdentifier(identifiers.getIdentifier());
322 reg.setSpecificIdentifier(identifiers.getLocalId());
323 }
324 Authentication authentication = userHelper.getAuthentication();
325 reg.setSubmitter((User)authentication.getPrincipal());
326 }
327 }
328
329 @Override
330 public boolean checkRegistrationExistsFor(TaxonName name) {
331
332 for(Registration reg : name.getRegistrations()){
333 if(minter != null){
334 if(minter.isFromOwnRegistration(reg.getIdentifier())){
335 return true;
336 }
337 } else {
338 return true; // first registrations wins as we can't distinguish them without a minter.
339 }
340 }
341 return false;
342 }
343
344 // =============================================================================================
345
346 }