ref #4770 handle unprotected titlecache for person2Team converter and some finetuning...
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / AgentServiceImpl.java
1 /**
2 * Copyright (C) 2007 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.util.ArrayList;
12 import java.util.List;
13 import java.util.UUID;
14
15 import org.apache.log4j.Logger;
16 import org.springframework.beans.factory.annotation.Autowired;
17 import org.springframework.stereotype.Service;
18 import org.springframework.transaction.annotation.Transactional;
19
20 import eu.etaxonomy.cdm.api.service.config.IIdentifiableEntityServiceConfigurator;
21 import eu.etaxonomy.cdm.api.service.pager.Pager;
22 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
23 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
24 import eu.etaxonomy.cdm.model.agent.Address;
25 import eu.etaxonomy.cdm.model.agent.AgentBase;
26 import eu.etaxonomy.cdm.model.agent.Institution;
27 import eu.etaxonomy.cdm.model.agent.InstitutionalMembership;
28 import eu.etaxonomy.cdm.model.agent.Person;
29 import eu.etaxonomy.cdm.model.agent.Team;
30 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
31 import eu.etaxonomy.cdm.model.common.CdmBase;
32 import eu.etaxonomy.cdm.persistence.dao.agent.IAgentDao;
33 import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;
34 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
35 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
36 import eu.etaxonomy.cdm.strategy.merge.ConvertMergeStrategy;
37 import eu.etaxonomy.cdm.strategy.merge.DefaultMergeStrategy;
38 import eu.etaxonomy.cdm.strategy.merge.IMergeStrategy;
39 import eu.etaxonomy.cdm.strategy.merge.MergeException;
40 import eu.etaxonomy.cdm.strategy.merge.MergeMode;
41
42 /**
43 * @author a.mueller
44 */
45 @Service
46 @Transactional(readOnly = true)
47 public class AgentServiceImpl
48 extends IdentifiableServiceBase<AgentBase,IAgentDao>
49 implements IAgentService {
50
51 private static final Logger logger = Logger.getLogger(AgentServiceImpl.class);
52
53 @Autowired
54 private ICdmGenericDao genericDao;
55
56 @Override
57 @Autowired
58 protected void setDao(IAgentDao dao) {
59 assert dao != null;
60 this.dao = dao;
61 }
62
63 /**
64 * Constructor
65 */
66 public AgentServiceImpl(){
67 if (logger.isDebugEnabled()) { logger.debug("Load AgentService Bean"); }
68 }
69
70
71 @Override
72 @Transactional(readOnly = false)
73 public UpdateResult updateCaches(Class<? extends AgentBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<AgentBase> cacheStrategy, IProgressMonitor monitor) {
74 if (clazz == null){
75 clazz = AgentBase.class;
76 }
77 return super.updateCachesImpl(clazz, stepSize, cacheStrategy, monitor);
78 }
79
80 @Override
81 public List<Institution> searchInstitutionByCode(String code) {
82 return dao.getInstitutionByCode(code);
83 }
84
85 @Override
86 public Pager<InstitutionalMembership> getInstitutionalMemberships(Person person, Integer pageSize, Integer pageNumber) {
87 long numberOfResults = dao.countInstitutionalMemberships(person);
88
89 List<InstitutionalMembership> results = new ArrayList<>();
90 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
91 results = dao.getInstitutionalMemberships(person, pageSize, pageNumber);
92 }
93
94 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
95 }
96
97 @Override
98 public Pager<Person> getMembers(Team team, Integer pageSize, Integer pageNumber) {
99 long numberOfResults = dao.countMembers(team);
100
101 List<Person> results = new ArrayList<>();
102 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
103 results = dao.getMembers(team, pageSize, pageNumber);
104 }
105
106 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
107 }
108
109 @Override
110 public Pager<Address> getAddresses(AgentBase agent, Integer pageSize, Integer pageNumber) {
111 long numberOfResults = dao.countAddresses(agent);
112
113 List<Address> results = new ArrayList<>();
114 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
115 results = dao.getAddresses(agent, pageSize, pageNumber);
116 }
117
118 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
119 }
120
121 @Override
122 public List<UuidAndTitleCache<Team>> getTeamUuidAndNomenclaturalTitle() {
123 return dao.getTeamUuidAndNomenclaturalTitle();
124 }
125
126 @Override
127 public List<UuidAndTitleCache<Person>> getPersonUuidAndTitleCache() {
128 return dao.getPersonUuidAndTitleCache();
129 }
130
131 @Override
132 public List<UuidAndTitleCache<Team>> getTeamUuidAndTitleCache() {
133 return dao.getTeamUuidAndTitleCache();
134 }
135
136 @Override
137 public List<UuidAndTitleCache<AgentBase>> getInstitutionUuidAndTitleCache(Integer limit, String pattern) {
138 return dao.getUuidAndAbbrevTitleCache(Institution.class, limit, pattern);
139 }
140
141 @Override
142 @Transactional(readOnly = false)
143 public DeleteResult delete(UUID agentUUID){
144 DeleteResult result = new DeleteResult();
145 if (agentUUID == null){
146 result.setAbort();
147 result.addException(new Exception("Can't delete object without UUID."));
148 return result;
149 }
150 AgentBase base = dao.load(agentUUID);
151 result = isDeletable(agentUUID, null);
152
153 if (result.isOk()){
154 if (base instanceof Team){
155 Team baseTeam = (Team) base;
156 List<Person> members = baseTeam.getTeamMembers();
157 List<Person> temp = new ArrayList<>();
158 for (Person member:members){
159 temp.add(member);
160 }
161 for (Person member: temp){
162 members.remove(member);
163 }
164 }
165 saveOrUpdate(base);
166
167 dao.delete(base);
168 result.addDeletedObject(base);
169
170 }
171
172 return result;
173 }
174
175 @Override
176 public DeleteResult delete(AgentBase agent){
177 return delete(agent.getUuid());
178 }
179
180 @Override
181 @Transactional(readOnly = false)
182 public UpdateResult convertTeam2Person(UUID teamUuid) throws MergeException {
183 Team team = CdmBase.deproxy(dao.load(teamUuid), Team.class);
184 return convertTeam2Person(team);
185 }
186
187 @Override
188 public UpdateResult convertTeam2Person(Team team) throws MergeException {
189 UpdateResult result = new UpdateResult();
190 Person newPerson = null;
191 team = CdmBase.deproxy(team, Team.class);
192 if (team.getTeamMembers().size() > 1){
193 throw new IllegalArgumentException("Team must not have more than 1 member to be convertable into a person");
194 }else if (team.getTeamMembers().size() == 1){
195 newPerson = team.getTeamMembers().get(0);
196 IMergeStrategy strategy = DefaultMergeStrategy.NewInstance(TeamOrPersonBase.class);
197 strategy.setDefaultCollectionMergeMode(MergeMode.FIRST);
198 genericDao.merge(newPerson, team, strategy);
199 }else if (team.getTeamMembers().isEmpty()){
200 newPerson = Person.NewInstance();
201 genericDao.save(newPerson);
202 IMergeStrategy strategy = DefaultMergeStrategy.NewInstance(TeamOrPersonBase.class);
203 strategy.setDefaultMergeMode(MergeMode.SECOND);
204 strategy.setDefaultCollectionMergeMode(MergeMode.SECOND);
205 genericDao.merge(newPerson, team, strategy);
206 }else{
207 throw new IllegalStateException("Unhandled state of team members collection");
208 }
209 result.setCdmEntity(newPerson);
210 return result;
211 }
212
213 @Override
214 @Transactional(readOnly = false)
215 public UpdateResult convertPerson2Team(UUID personUuid) throws MergeException, IllegalArgumentException {
216 Person person = CdmBase.deproxy(dao.load(personUuid), Person.class);
217 return convertPerson2Team(person);
218 }
219
220 @Override
221 public UpdateResult convertPerson2Team(Person person) throws MergeException, IllegalArgumentException {
222 UpdateResult result = new UpdateResult();
223 Team team = Team.NewInstance();
224 ConvertMergeStrategy strategy = ConvertMergeStrategy.NewInstance(TeamOrPersonBase.class);
225 strategy.setDefaultMergeMode(MergeMode.SECOND);
226 strategy.setDefaultCollectionMergeMode(MergeMode.SECOND);
227 team.setProtectedTitleCache(true);
228 strategy.setMergeMode("protectedTitleCache", MergeMode.FIRST); //as we do not add team members, the titleCache of the new team should be always protected
229 strategy.setDeleteSecondObject(true);
230
231 if (! genericDao.isMergeable(team, person, strategy)){
232 throw new MergeException("Person can not be transformed into team.");
233 }
234 try {
235 team.setProtectedNomenclaturalTitleCache(false);
236 if (person.isProtectedTitleCache() || !person.getTitleCache().startsWith("Person#")){
237 team.setTitleCache(person.getTitleCache(), true);
238 }
239 team.setNomenclaturalTitle(person.getNomenclaturalTitle(), true);
240 team = this.save(team);
241 genericDao.merge(team, person, strategy);
242 //team.addTeamMember(person); it is not wanted to keep the person as member
243
244 } catch (Exception e) {
245 throw new MergeException("Unhandled merge exception", e);
246 }
247 result.setCdmEntity(team);
248 result.addUpdatedObject(team);
249 return result;
250 }
251
252 @Override
253 public List<UuidAndTitleCache<AgentBase>> getUuidAndAbbrevTitleCache(Class clazz, Integer limit, String pattern) {
254 return dao.getUuidAndAbbrevTitleCache(clazz, null, pattern);
255 }
256
257 @Override
258 public List<AgentBase> findByTitleAndAbbrevTitle(IIdentifiableEntityServiceConfigurator<AgentBase> config){
259 return dao.findByTitleAndAbbrevTitle(config.getClazz(),config.getTitleSearchStringSqlized(), config.getMatchMode(), config.getCriteria(), config.getPageSize(), config.getPageNumber(), config.getOrderHints(), config.getPropertyPaths());
260 }
261 }