ref #7651 #7622 using nameService instead of CdmRepository to avoid bean factory...
[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.List;
16 import java.util.Optional;
17 import java.util.Set;
18 import java.util.UUID;
19
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.security.core.Authentication;
22 import org.springframework.stereotype.Service;
23 import org.springframework.transaction.annotation.Transactional;
24
25 import eu.etaxonomy.cdm.api.service.idminter.IdentifierMinter.Identifier;
26 import eu.etaxonomy.cdm.api.service.idminter.RegistrationIdentifierMinter;
27 import eu.etaxonomy.cdm.api.service.pager.Pager;
28 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
29 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
30 import eu.etaxonomy.cdm.api.utility.UserHelper;
31 import eu.etaxonomy.cdm.model.common.User;
32 import eu.etaxonomy.cdm.model.name.Registration;
33 import eu.etaxonomy.cdm.model.name.RegistrationStatus;
34 import eu.etaxonomy.cdm.model.name.TaxonName;
35 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
36 import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
37 import eu.etaxonomy.cdm.model.reference.Reference;
38 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
39 import eu.etaxonomy.cdm.persistence.dao.name.IRegistrationDao;
40 import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;
41 import eu.etaxonomy.cdm.persistence.query.MatchMode;
42 import eu.etaxonomy.cdm.persistence.query.OrderHint;
43
44 /**
45 * @author a.kohlbecker
46 * @since May 2, 2017
47 *
48 */
49 @Service
50 @Transactional(readOnly = true)
51 public class RegistrationServiceImpl extends AnnotatableServiceBase<Registration, IRegistrationDao> implements IRegistrationService {
52
53 /**
54 * {@inheritDoc}
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
69 @Autowired
70 private INameService nameService;
71
72
73 /**
74 * {@inheritDoc}
75 */
76 @Override
77 @Transactional(readOnly = true)
78 public Pager<Registration> page(Optional<Reference> reference, Collection<RegistrationStatus> includedStatus,
79 Integer pageSize, Integer pageIndex, List<String> propertyPaths) {
80
81 long numberOfResults = dao.count(reference, includedStatus);
82
83 List<Registration> results = new ArrayList<>();
84 Integer [] limitStart = AbstractPagerImpl.limitStartforRange(numberOfResults, pageIndex, pageSize);
85 if(limitStart != null) {
86 results = dao.list(reference, includedStatus, limitStart[0], limitStart[1], propertyPaths);
87 }
88
89 return new DefaultPagerImpl<>(pageIndex, numberOfResults, pageSize, results);
90 }
91
92 /**
93 * {@inheritDoc}
94 */
95 @Override
96 @Transactional(readOnly = true)
97 public Pager<Registration> page(User submitter, Collection<RegistrationStatus> includedStatus,
98 String identifierFilterPattern, String taxonNameFilterPattern, Set<TypeDesignationStatusBase> typeDesignationStatus,
99 Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths) {
100
101 List<Restriction<? extends Object>> restrictions = new ArrayList<>();
102
103 if( !userHelper.userIsAutheticated() || userHelper.userIsAnnonymous() ) {
104 includedStatus = Arrays.asList(RegistrationStatus.PUBLISHED);
105 }
106
107 if(submitter != null){
108 restrictions.add(new Restriction<>("submitter", MatchMode.EXACT, submitter));
109 }
110 if(includedStatus != null && !includedStatus.isEmpty()){
111 restrictions.add(new Restriction<>("status", MatchMode.EXACT, includedStatus.toArray(new RegistrationStatus[includedStatus.size()])));
112 }
113 if(identifierFilterPattern != null){
114 restrictions.add(new Restriction<>("identifier", MatchMode.LIKE, identifierFilterPattern));
115 }
116 if(taxonNameFilterPattern != null){
117 restrictions.add(new Restriction<>("name.titleCache", MatchMode.LIKE, taxonNameFilterPattern));
118 }
119 if(typeDesignationStatus != null){
120 restrictions.add(new Restriction<>("typeDesignations.typeStatus", null, typeDesignationStatus.toArray(new TypeDesignationStatusBase[typeDesignationStatus.size()])));
121 }
122
123 long numberOfResults = dao.count(Registration.class, restrictions);
124
125 List<Registration> results = new ArrayList<>();
126 Integer [] limitStart = AbstractPagerImpl.limitStartforRange(numberOfResults, pageIndex, pageSize);
127 if(limitStart != null) {
128 results = dao.list(Registration.class, restrictions, limitStart[0], limitStart[1], orderHints, propertyPaths);
129 }
130
131 return new DefaultPagerImpl<>(pageIndex, numberOfResults, pageSize, results);
132 }
133
134 @Override
135 @Transactional(readOnly = true)
136 public Pager<Registration> page(UUID submitterUuid, Collection<RegistrationStatus> includedStatus,
137 String identifierFilterPattern, String taxonNameFilterPattern, Collection<UUID> typeDesignationStatusUuids,
138 Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths) {
139
140 List<Restriction<? extends Object>> restrictions = new ArrayList<>();
141
142 if( !userHelper.userIsAutheticated() || userHelper.userIsAnnonymous() ) {
143 includedStatus = Arrays.asList(RegistrationStatus.PUBLISHED);
144 }
145
146 if(submitterUuid != null){
147 restrictions.add(new Restriction<>("submitter.uuid", null, submitterUuid));
148 }
149 if(includedStatus != null && !includedStatus.isEmpty()){
150 restrictions.add(new Restriction<>("status", null, includedStatus.toArray(new RegistrationStatus[includedStatus.size()])));
151 }
152 if(identifierFilterPattern != null){
153 restrictions.add(new Restriction<>("identifier", MatchMode.LIKE, identifierFilterPattern));
154 }
155 if(taxonNameFilterPattern != null){
156 restrictions.add(new Restriction<>("name.titleCache", MatchMode.LIKE, taxonNameFilterPattern));
157 }
158 if(typeDesignationStatusUuids != null){
159 restrictions.add(new Restriction<>("typeDesignations.typeStatus.uuid", null, typeDesignationStatusUuids.toArray(new UUID[typeDesignationStatusUuids.size()])));
160 }
161
162 long numberOfResults = dao.count(Registration.class, restrictions);
163
164 List<Registration> results = new ArrayList<>();
165 if(pageIndex == null){
166 pageIndex = 0;
167 }
168 Integer [] limitStart = AbstractPagerImpl.limitStartforRange(numberOfResults, pageIndex, pageSize);
169 if(limitStart != null) {
170 results = dao.list(Registration.class, restrictions, limitStart[0], limitStart[1], orderHints, propertyPaths);
171 }
172
173 return new DefaultPagerImpl<>(pageIndex, numberOfResults, pageSize, results);
174 }
175
176 /**
177 * @param identifier
178 * @param validateUniqueness
179 * @param response
180 * @return
181 * @throws IOException
182 */
183 @Override
184 @Transactional(readOnly = true)
185 public Pager<Registration> pageByIdentifier(String identifier, Integer pageIndex, Integer pageSize, List<String> propertyPaths) throws IOException {
186
187 List<Restriction<?>> restrictions = new ArrayList<>();
188 if( !userHelper.userIsAutheticated() || userHelper.userIsAnnonymous() ) {
189 restrictions.add(new Restriction<>("status", null, RegistrationStatus.PUBLISHED));
190 }
191
192 Pager<Registration> regPager = pageByRestrictions(Registration.class, "identifier", identifier, MatchMode.EXACT,
193 restrictions, pageSize, pageIndex, null, propertyPaths);
194
195
196 return regPager;
197 }
198
199 // ============= functionality to be moved into a "RegistrationManagerBean" ==================
200
201
202 /**
203 * Factory Method
204 * TODO move into RegistrationFactory
205 *
206 * @return a new Registration instance with submitter set to the current authentications principal
207 */
208 @Override
209 public Registration newRegistration() {
210
211 Registration reg = Registration.NewInstance(
212 null,
213 null,
214 null,
215 null);
216 Authentication authentication = userHelper.getAuthentication();
217 reg.setSubmitter((User)authentication.getPrincipal());
218 return reg;
219 }
220
221 /**
222 * @param taxonNameId
223 * @return
224 */
225 @Override
226 @Transactional(readOnly=false)
227 public Registration createRegistrationForName(UUID taxonNameUuid) {
228
229 Registration reg = Registration.NewInstance(
230 null,
231 null,
232 taxonNameUuid != null ? nameService.load(taxonNameUuid, Arrays.asList("nomenclaturalReference.inReference")) : null,
233 null);
234
235 reg = assureIsPersisted(reg);
236
237 return load(reg.getUuid(), Arrays.asList(new String []{"blockedBy"}));
238 }
239
240 /**
241 * @param typeDesignationTarget
242 */
243 @Override
244 @Transactional(readOnly=false)
245 public Registration assureIsPersisted(Registration reg) {
246
247 if(reg.isPersited()){
248 return reg;
249 }
250
251 prepareForSave(reg);
252 reg = save(reg);
253 userHelper.createAuthorityForCurrentUser(Registration.class, reg.getUuid(), Operation.UPDATE, RegistrationStatus.PREPARATION.name());
254
255 return reg;
256 }
257
258 @Override
259 @Transactional(readOnly=false)
260 public void addTypeDesignation(UUID registrationUUID, UUID typeDesignationUuid){
261
262 // load the typeDesignations with the registration so that typified names can not be twice in detached sessions
263 // otherwise multiple representation problems might occur
264 Registration registration = load(registrationUUID, Arrays.asList("typeDesignations"));
265 if(registration == null){
266 registration = newRegistration();
267 registration = assureIsPersisted(registration);
268 }
269 TypeDesignationBase<?> nameTypeDesignation = nameService.loadTypeDesignation(typeDesignationUuid, Arrays.asList(""));
270 registration.getTypeDesignations().add(nameTypeDesignation);
271 }
272
273 /**
274 * Sets the registration identifier and submitter in case the registration is not yet persisted.
275 *
276 * @param reg
277 * The Registration to prepare for saving.
278 */
279 private void prepareForSave(Registration reg) {
280
281 if(!reg.isPersited()){
282 if(minter != null){
283 Identifier<String> identifiers = minter.mint();
284 if(identifiers.getIdentifier() == null){
285 throw new RuntimeException("RegistrationIdentifierMinter configuration incomplete.");
286 }
287 reg.setIdentifier(identifiers.getIdentifier());
288 reg.setSpecificIdentifier(identifiers.getLocalId());
289 }
290 Authentication authentication = userHelper.getAuthentication();
291 reg.setSubmitter((User)authentication.getPrincipal());
292 }
293 }
294
295 /**
296 * @param name
297 */
298 @Override
299 public boolean checkRegistrationExistsFor(TaxonName name) {
300
301 for(Registration reg : name.getRegistrations()){
302 if(minter != null){
303 if(minter.isFromOwnRegistration(reg.getIdentifier())){
304 return true;
305 }
306 } else {
307 return true; // first registrations wins as we can't distinguish them without a minter.
308 }
309 }
310 return false;
311 }
312
313 // =============================================================================================
314
315
316 }