Project

General

Profile

Download (15.8 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2007 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10

    
11
package eu.etaxonomy.cdm.api.service;
12

    
13
import java.net.URI;
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Enumeration;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.List;
20
import java.util.Locale;
21
import java.util.Set;
22
import java.util.UUID;
23

    
24
import org.apache.commons.lang.StringUtils;
25
import org.apache.log4j.Logger;
26
import org.springframework.beans.factory.annotation.Autowired;
27
import org.springframework.beans.factory.annotation.Qualifier;
28
import org.springframework.stereotype.Service;
29
import org.springframework.transaction.annotation.Transactional;
30

    
31
import eu.etaxonomy.cdm.api.service.UpdateResult.Status;
32
import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;
33
import eu.etaxonomy.cdm.api.service.config.TermDeletionConfigurator;
34
import eu.etaxonomy.cdm.api.service.exception.DataChangeNoRollbackException;
35
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
36
import eu.etaxonomy.cdm.api.service.pager.Pager;
37
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
38
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
39
import eu.etaxonomy.cdm.model.common.CdmBase;
40
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
41
import eu.etaxonomy.cdm.model.common.Language;
42
import eu.etaxonomy.cdm.model.common.LanguageString;
43
import eu.etaxonomy.cdm.model.common.LanguageStringBase;
44
import eu.etaxonomy.cdm.model.common.Representation;
45
import eu.etaxonomy.cdm.model.common.TermType;
46
import eu.etaxonomy.cdm.model.common.TermVocabulary;
47
import eu.etaxonomy.cdm.model.location.NamedArea;
48
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
49
import eu.etaxonomy.cdm.model.location.NamedAreaType;
50
import eu.etaxonomy.cdm.model.media.Media;
51
import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
52
import eu.etaxonomy.cdm.persistence.dao.common.ILanguageStringBaseDao;
53
import eu.etaxonomy.cdm.persistence.dao.common.ILanguageStringDao;
54
import eu.etaxonomy.cdm.persistence.dao.common.IRepresentationDao;
55
import eu.etaxonomy.cdm.persistence.query.OrderHint;
56
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
57

    
58
@Service
59
@Transactional(readOnly = true)
60
public class TermServiceImpl extends IdentifiableServiceBase<DefinedTermBase,IDefinedTermDao> implements ITermService{
61
	@SuppressWarnings("unused")
62
	private static final Logger logger = Logger.getLogger(TermServiceImpl.class);
63

    
64
	private ILanguageStringDao languageStringDao;
65

    
66
	@Autowired
67
	@Qualifier("langStrBaseDao")
68
	private ILanguageStringBaseDao languageStringBaseDao;
69
	private IRepresentationDao representationDao;
70

    
71
	@Autowired
72
	public void setLanguageStringDao(ILanguageStringDao languageStringDao) {
73
		this.languageStringDao = languageStringDao;
74
	}
75

    
76
	@Autowired
77
	public void setRepresentationDao(IRepresentationDao representationDao) {
78
		this.representationDao = representationDao;
79
	}
80

    
81
	@Override
82
    @Autowired
83
	protected void setDao(IDefinedTermDao dao) {
84
		this.dao = dao;
85
	}
86

    
87
	@Override
88
	public <T extends DefinedTermBase> List<T> listByTermType(TermType termType, Integer limit, Integer start,
89
	        List<OrderHint> orderHints, List<String> propertyPaths) {
90
	    return dao.listByTermType(termType, limit, start, orderHints, propertyPaths);
91
	}
92

    
93
	@Override
94
	public DefinedTermBase getByUri(URI uri) {
95
		return dao.findByUri(uri);
96
	}
97

    
98
	@Override
99
	public Language getLanguageByIso(String iso639) {
100
	    return dao.getLanguageByIso(iso639);
101
	}
102

    
103
	@Override
104
	public Language getLanguageByLabel(String label) {
105
	    return Language.getLanguageByLabel(label);
106
	}
107

    
108
	@Override
109
	public List<Language> getLanguagesByLocale(Enumeration<Locale> locales){
110
		return dao.getLanguagesByLocale(locales);
111
	}
112

    
113
	@Override
114
    public <TERM extends DefinedTermBase> TERM findByIdInVocabulary(String id, UUID vocabularyUuid, Class<TERM> clazz) throws IllegalArgumentException {
115
        List<TERM> list = dao.getDefinedTermByIdInVocabulary(id, vocabularyUuid, clazz, null, null);
116
		if (list.isEmpty()){
117
			return null;
118
		}else if (list.size() == 1){
119
			return list.get(0);
120
		}else{
121
			String message = "There is more then 1 (%d) term with the same id in vocabulary. This is forbidden. Check the state of your database.";
122
			throw new IllegalStateException(String.format(message, list.size()));
123
		}
124
	}
125

    
126

    
127
	@Override
128
	public NamedArea getAreaByTdwgAbbreviation(String tdwgAbbreviation) {
129
		if (StringUtils.isBlank(tdwgAbbreviation)){ //TDWG areas should always have a label
130
			return null;
131
		}
132
		List<NamedArea> list = dao.getDefinedTermByIdInVocabulary(tdwgAbbreviation, NamedArea.uuidTdwgAreaVocabulary, NamedArea.class, null, null);
133
		if (list.isEmpty()){
134
			return null;
135
		}else if (list.size() == 1){
136
			return list.get(0);
137
		}else{
138
			String message = "There is more then 1 (%d) TDWG area with the same abbreviated label. This is forbidden. Check the state of your database.";
139
			throw new IllegalStateException(String.format(message, list.size()));
140
		}
141
	}
142

    
143
	@Override
144
	public <T extends DefinedTermBase> Pager<T> getGeneralizationOf(T definedTerm, Integer pageSize, Integer pageNumber) {
145
        Integer numberOfResults = dao.countGeneralizationOf(definedTerm);
146

    
147
		List<T> results = new ArrayList<T>();
148
		if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
149
			results = dao.getGeneralizationOf(definedTerm, pageSize, pageNumber);
150
		}
151

    
152
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
153
	}
154

    
155
	@Override
156
	public <T extends DefinedTermBase> Pager<T> getIncludes(Collection<T> definedTerms, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
157
        Integer numberOfResults = dao.countIncludes(definedTerms);
158

    
159
		List<T> results = new ArrayList<T>();
160
		if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
161
			results = dao.getIncludes(definedTerms, pageSize, pageNumber,propertyPaths);
162
		}
163

    
164
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
165
	}
166

    
167
	@Override
168
	public Pager<Media> getMedia(DefinedTermBase definedTerm, Integer pageSize,	Integer pageNumber) {
169
        Integer numberOfResults = dao.countMedia(definedTerm);
170

    
171
		List<Media> results = new ArrayList<Media>();
172
		if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
173
			results = dao.getMedia(definedTerm, pageSize, pageNumber);
174
		}
175

    
176
		return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
177
	}
178

    
179
	@Override
180
	public <T extends DefinedTermBase> Pager<T> getPartOf(Set<T> definedTerms,Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
181
        Integer numberOfResults = dao.countPartOf(definedTerms);
182

    
183
		List<T> results = new ArrayList<T>();
184
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
185
			results = dao.getPartOf(definedTerms, pageSize, pageNumber, propertyPaths);
186
		}
187

    
188
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
189
	}
190

    
191
	@Override
192
	public Pager<NamedArea> list(NamedAreaLevel level, NamedAreaType type, Integer pageSize, Integer pageNumber,
193
			List<OrderHint> orderHints, List<String> propertyPaths) {
194
		Integer numberOfResults = dao.count(level, type);
195

    
196
		List<NamedArea> results = new ArrayList<NamedArea>();
197
		if (numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
198
			results = dao.list(level, type, pageSize, pageNumber, orderHints, propertyPaths);
199
		}
200

    
201
		return new DefaultPagerImpl<NamedArea>(pageNumber, numberOfResults, pageSize, results);
202
	}
203

    
204
	@Override
205
	public <T extends DefinedTermBase> Pager<T> findByRepresentationText(String label, Class<T> clazz, Integer pageSize, Integer pageNumber) {
206
        Integer numberOfResults = dao.countDefinedTermByRepresentationText(label,clazz);
207

    
208
		List<T> results = new ArrayList<T>();
209
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
210
			results = dao.getDefinedTermByRepresentationText(label, clazz, pageSize, pageNumber);
211
		}
212

    
213
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
214
	}
215

    
216
	@Override
217
	public <T extends DefinedTermBase> Pager<T> findByRepresentationAbbreviation(String abbrev, Class<T> clazz, Integer pageSize, Integer pageNumber) {
218
        Integer numberOfResults = dao.countDefinedTermByRepresentationAbbrev(abbrev,clazz);
219

    
220
		List<T> results = new ArrayList<T>();
221
		if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
222
			results = dao.getDefinedTermByRepresentationAbbrev(abbrev, clazz, pageSize, pageNumber);
223
		}
224

    
225
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
226
	}
227

    
228
	@Override
229
	public List<LanguageString> getAllLanguageStrings(int limit, int start) {
230
		return languageStringDao.list(limit, start);
231
	}
232

    
233
	@Override
234
	public List<Representation> getAllRepresentations(int limit, int start) {
235
		return representationDao.list(limit,start);
236
	}
237

    
238
	@Override
239
	public UUID saveLanguageData(LanguageStringBase languageData) {
240
		return languageStringBaseDao.save(languageData).getUuid();
241
	}
242

    
243

    
244
	/** @deprecated use {@link #delete(DefinedTermBase, TermDeletionConfigurator)} instead
245
	 * to allow DeleteResult return type*/
246
	@Override
247
	@Deprecated
248
	public DeleteResult delete(DefinedTermBase term){
249
		DeleteResult result = new DeleteResult();
250

    
251
		TermDeletionConfigurator defaultConfig = new TermDeletionConfigurator();
252
		result = delete(term, defaultConfig);
253
		return result;
254
	}
255

    
256
	@Override
257
	@Deprecated
258
	@Transactional(readOnly = false)
259
	public DeleteResult delete(UUID termUuid){
260
	    DeleteResult result = new DeleteResult();
261

    
262
	    TermDeletionConfigurator defaultConfig = new TermDeletionConfigurator();
263
	    result = delete(dao.load(termUuid), defaultConfig);
264
	    return result;
265
	}
266

    
267
	@Override
268
	public DeleteResult delete(DefinedTermBase term, TermDeletionConfigurator config){
269
		if (config == null){
270
			config = new TermDeletionConfigurator();
271
		}
272
//		boolean isInternal = config.isInternal();
273

    
274
		Set<DefinedTermBase> termsToSave = new HashSet<DefinedTermBase>();
275

    
276
		DeleteResult result = isDeletable(term, config);
277
		//CdmBase.deproxy(dao.merge(term), DefinedTermBase.class);
278
		try {
279
			//generalization of
280
			Set<DefinedTermBase> specificTerms = term.getGeneralizationOf();
281
			if (specificTerms.size()>0){
282
				if (config.isDeleteGeneralizationOfRelations()){
283
					DefinedTermBase generalTerm = term.getKindOf();
284
					for (DefinedTermBase specificTerm: specificTerms){
285
						term.removeGeneralization(specificTerm);
286
						if (generalTerm != null){
287
							generalTerm.addGeneralizationOf(specificTerm);
288
							termsToSave.add(generalTerm);
289
						}
290
					}
291
				}else{
292
					//TODO Exception type
293
					String message = "This term has specifing terms. Move or delete specifiing terms prior to delete or change delete configuration.";
294
					result.addRelatedObjects(specificTerms);
295
					result.setAbort();
296
					Exception ex = new DataChangeNoRollbackException(message);
297
					result.addException(ex);
298
				}
299
			}
300

    
301
			//kind of
302
			DefinedTermBase generalTerm = term.getKindOf();
303
			if (generalTerm != null){
304
				if (config.isDeleteKindOfRelations()){
305
					generalTerm.removeGeneralization(term);
306
				}else{
307
					//TODO Exception type
308
					String message = "This term is kind of another term. Move or delete kind of relationship prior to delete or change delete configuration.";
309
					result.addRelatedObject(generalTerm);
310
					result.setAbort();
311
					DataChangeNoRollbackException ex = new DataChangeNoRollbackException(message);
312
					result.addException(ex);
313
					throw ex;
314
				}
315
			}
316

    
317
			//part of
318
			DefinedTermBase parentTerm = term.getPartOf();
319
			if (parentTerm != null){
320
				if (! config.isDeletePartOfRelations()){
321
					//TODO Exception type
322
					String message = "This term is included in another term. Remove from parent term prior to delete or change delete configuration.";
323
					result.addRelatedObject(parentTerm);
324
					result.setAbort();
325
					DataChangeNoRollbackException ex = new DataChangeNoRollbackException(message);
326
					result.addException(ex);
327
				}
328
			}
329

    
330

    
331
			//included in
332
			Set<DefinedTermBase> includedTerms = term.getIncludes();
333
			if (includedTerms.size()> 0){
334
//				if (config.isDeleteIncludedTerms()){
335
//					for (DefinedTermBase includedTerm: includedTerms){
336
//						config.setCheck(true);
337
//						DeleteResult includedResult = this.delete(includedTerm, config);
338
////						config.setCheck(isCheck);
339
//						result.includeResult(includedResult);
340
//					}
341
//				}else
342
					if (config.isDeleteIncludedRelations()){
343
					DefinedTermBase parent = term.getPartOf();
344
					for (DefinedTermBase includedTerm: includedTerms){
345
						term.removeIncludes(includedTerm);
346
						if (parent != null){
347
							parent.addIncludes(includedTerm);
348
							termsToSave.add(parent);
349
						}
350
					}
351
				}else{
352
					//TODO Exception type
353
					String message = "This term includes other terms. Move or delete included terms prior to delete or change delete configuration.";
354
					result.addRelatedObjects(includedTerms);
355
					result.setAbort();
356
					Exception ex = new DataChangeNoRollbackException(message);
357
					result.addException(ex);
358
				}
359
			}
360

    
361
			//part of
362
			if (parentTerm != null){
363
				if (config.isDeletePartOfRelations()){
364
					parentTerm.removeIncludes(term);
365
					termsToSave.add(parentTerm);
366
				}else{
367
					//handelede before "included in"
368
				}
369
			}
370

    
371
//			relatedObjects;
372

    
373

    
374
			if (result.isOk()){
375
				TermVocabulary voc = term.getVocabulary();
376
				if (voc!= null){
377
					voc.removeTerm(term);
378
				}
379
				//TODO save voc
380
				if (true /*!config.isInternal()*/){
381
					dao.delete(term);
382
					dao.saveOrUpdateAll(termsToSave);
383
//					for (DeleteResult.PersistPair persistPair : result.getObjectsToDelete()){
384
//						persistPair.dao.delete(persistPair.objectToPersist);
385
//					}
386
//					for (DeleteResult.PersistPair persistPair : result.getObjectsToSave()){
387
//						persistPair.dao.saveOrUpdate(persistPair.objectToPersist);
388
//					}
389

    
390
				}
391
			}
392
		} catch (DataChangeNoRollbackException e) {
393
			result.setStatus(Status.ERROR);
394
		}
395
		return result;
396
	}
397

    
398
	@Override
399
	@Transactional(readOnly = false)
400
	public DeleteResult delete(UUID termUuid, TermDeletionConfigurator config){
401
	    return delete(dao.load(termUuid), config);
402
	}
403

    
404
	@Override
405
	@Transactional(readOnly = false)
406
    public void updateTitleCache(Class<? extends DefinedTermBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DefinedTermBase> cacheStrategy, IProgressMonitor monitor) {
407
		//TODO shouldnt this be TermBase instead of DefinedTermBase
408
		if (clazz == null){
409
			clazz = DefinedTermBase.class;
410
		}
411
		super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
412
	}
413

    
414
	@Override
415
    public DeleteResult isDeletable(DefinedTermBase term, DeleteConfiguratorBase config){
416
        DeleteResult result = new DeleteResult();
417
        Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(term);
418
        if (references != null){
419
            result.addRelatedObjects(references);
420
            Iterator<CdmBase> iterator = references.iterator();
421
            CdmBase ref;
422
            while (iterator.hasNext()){
423
                ref = iterator.next();
424
                if (ref instanceof TermVocabulary){
425
                    result.getRelatedObjects().remove(ref);
426
                }else{
427

    
428
                    String message = "An object of " + ref.getClass().getName() + " with ID " + ref.getId() + " is referencing the object" ;
429
                    result.addException(new ReferencedObjectUndeletableException(message));
430
                    result.setAbort();
431
                }
432

    
433
            }
434
        }
435
        return result;
436
    }
437

    
438
}
(91-91/97)