2 * Copyright (C) 2007 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
.util
.ArrayList
;
12 import java
.util
.List
;
13 import java
.util
.UUID
;
15 import org
.apache
.commons
.lang3
.StringUtils
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
18 import org
.springframework
.stereotype
.Service
;
19 import org
.springframework
.transaction
.annotation
.Transactional
;
21 import eu
.etaxonomy
.cdm
.api
.service
.config
.IIdentifiableEntityServiceConfigurator
;
22 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
23 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
24 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
25 import eu
.etaxonomy
.cdm
.model
.agent
.Address
;
26 import eu
.etaxonomy
.cdm
.model
.agent
.AgentBase
;
27 import eu
.etaxonomy
.cdm
.model
.agent
.Institution
;
28 import eu
.etaxonomy
.cdm
.model
.agent
.InstitutionalMembership
;
29 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
30 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
31 import eu
.etaxonomy
.cdm
.model
.agent
.TeamOrPersonBase
;
32 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
33 import eu
.etaxonomy
.cdm
.persistence
.dao
.agent
.IAgentDao
;
34 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
35 import eu
.etaxonomy
.cdm
.persistence
.dto
.UuidAndTitleCache
;
36 import eu
.etaxonomy
.cdm
.strategy
.cache
.common
.IIdentifiableEntityCacheStrategy
;
37 import eu
.etaxonomy
.cdm
.strategy
.merge
.ConvertMergeStrategy
;
38 import eu
.etaxonomy
.cdm
.strategy
.merge
.DefaultMergeStrategy
;
39 import eu
.etaxonomy
.cdm
.strategy
.merge
.IMergeStrategy
;
40 import eu
.etaxonomy
.cdm
.strategy
.merge
.MergeException
;
41 import eu
.etaxonomy
.cdm
.strategy
.merge
.MergeMode
;
47 @Transactional(readOnly
= true)
48 public class AgentServiceImpl
49 extends IdentifiableServiceBase
<AgentBase
,IAgentDao
>
50 implements IAgentService
{
52 private static final Logger logger
= Logger
.getLogger(AgentServiceImpl
.class);
55 private ICdmGenericDao genericDao
;
59 protected void setDao(IAgentDao dao
) {
67 public AgentServiceImpl(){
68 if (logger
.isDebugEnabled()) { logger
.debug("Load AgentService Bean"); }
72 @Transactional(readOnly
= false)
73 public UpdateResult
updateCaches(Class
<?
extends AgentBase
> clazz
, Integer stepSize
, IIdentifiableEntityCacheStrategy
<AgentBase
> cacheStrategy
, IProgressMonitor monitor
) {
75 clazz
= AgentBase
.class;
77 return super.updateCachesImpl(clazz
, stepSize
, cacheStrategy
, monitor
);
81 public List
<Institution
> searchInstitutionByCode(String code
) {
82 return dao
.getInstitutionByCode(code
);
86 public Pager
<InstitutionalMembership
> getInstitutionalMemberships(Person person
, Integer pageSize
, Integer pageNumber
) {
87 long numberOfResults
= dao
.countInstitutionalMemberships(person
);
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
);
94 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
98 public Pager
<Person
> getMembers(Team team
, Integer pageSize
, Integer pageNumber
) {
99 long numberOfResults
= dao
.countMembers(team
);
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
);
106 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
110 public Pager
<Address
> getAddresses(AgentBase agent
, Integer pageSize
, Integer pageNumber
) {
111 long numberOfResults
= dao
.countAddresses(agent
);
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
);
118 return new DefaultPagerImpl
<>(pageNumber
, numberOfResults
, pageSize
, results
);
122 public List
<UuidAndTitleCache
<Team
>> getTeamUuidAndNomenclaturalTitle() {
123 return dao
.getTeamUuidAndNomenclaturalTitle();
127 public List
<UuidAndTitleCache
<Person
>> getPersonUuidAndTitleCache() {
128 return dao
.getPersonUuidAndTitleCache();
132 public List
<UuidAndTitleCache
<Team
>> getTeamUuidAndTitleCache() {
133 return dao
.getTeamUuidAndTitleCache();
137 public List
<UuidAndTitleCache
<Institution
>> getInstitutionUuidAndTitleCache(Integer limit
, String pattern
) {
138 return dao
.getUuidAndAbbrevTitleCache(Institution
.class, limit
, pattern
);
142 @Transactional(readOnly
= false)
143 public DeleteResult
delete(UUID agentUUID
){
144 DeleteResult result
= new DeleteResult();
145 if (agentUUID
== null){
147 result
.addException(new Exception("Can't delete object without UUID."));
150 AgentBase base
= dao
.load(agentUUID
);
151 result
= isDeletable(agentUUID
, null);
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
){
161 for (Person member
: temp
){
162 members
.remove(member
);
168 result
.addDeletedObject(base
);
176 public DeleteResult
delete(AgentBase agent
){
177 return delete(agent
.getUuid());
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
);
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
);
207 throw new IllegalStateException("Unhandled state of team members collection");
209 result
.setCdmEntity(newPerson
);
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
);
221 public UpdateResult
convertPerson2Team(Person person
) throws MergeException
, IllegalArgumentException
{
223 throw new IllegalArgumentException("Person does not exist.");
225 UpdateResult result
= new UpdateResult();
226 Team team
= Team
.NewInstance();
227 ConvertMergeStrategy strategy
= ConvertMergeStrategy
.NewInstance(TeamOrPersonBase
.class);
228 strategy
.setDefaultMergeMode(MergeMode
.SECOND
);
229 strategy
.setDefaultCollectionMergeMode(MergeMode
.SECOND
);
230 if (person
.isProtectedTitleCache() || !person
.getTitleCache().startsWith("Person#")){ //the later is for checking if the person is empty, this can be done better
231 team
.setTitleCache(person
.getTitleCache(), true); //as there are no members we set the titleCache to protected (as long as titleCache does not take the protected nomenclatural title but results in '-empty team-' in this situation); for some reason it is necessary to also set the title cache as well here, otherwise it is recomputed during the merge
233 strategy
.setMergeMode("protectedTitleCache", MergeMode
.FIRST
); //as we do not add team members, the titleCache of the new team should be always protected
234 strategy
.setDeleteSecondObject(true);
235 if (StringUtils
.isNotBlank(person
.getNomenclaturalTitle())){
236 team
.setNomenclaturalTitleCache(person
.getNomenclaturalTitle(), true); //sets the protected flag always to true, this is necessary as long as person does not have a nomenclatural title cache; maybe setting the protected title itself is not necessary but does no harm
238 if (StringUtils
.isNotBlank(person
.getCollectorTitle())){
239 team
.setCollectorTitleCache(person
.getCollectorTitle(), true); //sets the protected flag always to true, this is necessary as long as person does not have a collector title cache; maybe setting the protected title itself is not necessary but does no harm
242 if (! genericDao
.isMergeable(team
, person
, strategy
)){
243 throw new MergeException("Person can not be transformed into team.");
246 team
= this.save(team
);
247 genericDao
.merge(team
, person
, strategy
);
249 //Note: we decided never add the old person as (first) member of the team as there are not many usecases for this.
250 //But we may try to parse the old person into members which may handle the case that teams have been stored as unparsed persons
252 } catch (Exception e
) {
253 throw new MergeException("Unhandled merge exception", e
);
255 result
.setCdmEntity(team
);
256 result
.addUpdatedObject(team
);
261 public <T
extends AgentBase
> List
<UuidAndTitleCache
<T
>> getUuidAndAbbrevTitleCache(Class
<T
> clazz
, Integer limit
, String pattern
) {
262 return dao
.getUuidAndAbbrevTitleCache(clazz
, null, pattern
);
266 public <T
extends AgentBase
<?
>> List
<T
> findByTitleAndAbbrevTitle(IIdentifiableEntityServiceConfigurator
<T
> config
){
267 return dao
.findByTitleAndAbbrevTitle(config
.getClazz(),config
.getTitleSearchStringSqlized(), config
.getMatchMode(), config
.getCriteria(), config
.getPageSize(), config
.getPageNumber(), config
.getOrderHints(), config
.getPropertyPaths());