Project

General

Profile

Download (16.2 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
	/* (non-Javadoc)
88
	 * @see eu.etaxonomy.cdm.api.service.ITermService#listByTermType(eu.etaxonomy.cdm.model.common.TermType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
89
	 */
90
	@Override
91
	public <T extends DefinedTermBase> List<T> listByTermType(TermType termType, Integer limit, Integer start,
92
	        List<OrderHint> orderHints, List<String> propertyPaths) {
93
	    return dao.listByTermType(termType, limit, start, orderHints, propertyPaths);
94
	}
95

    
96
	@Override
97
	public DefinedTermBase getByUri(URI uri) {
98
		return dao.findByUri(uri);
99
	}
100

    
101
	@Override
102
	public Language getLanguageByIso(String iso639) {
103
	    return dao.getLanguageByIso(iso639);
104
	}
105

    
106
	@Override
107
	public Language getLanguageByLabel(String label) {
108
	    return Language.getLanguageByLabel(label);
109
	}
110

    
111
	@Override
112
	public List<Language> getLanguagesByLocale(Enumeration<Locale> locales){
113
		return dao.getLanguagesByLocale(locales);
114
	}
115

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

    
129

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

    
145
	}
146

    
147
	@Override
148
	public <T extends DefinedTermBase> Pager<T> getGeneralizationOf(T definedTerm, Integer pageSize, Integer pageNumber) {
149
        Integer numberOfResults = dao.countGeneralizationOf(definedTerm);
150

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

    
156
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
157
	}
158

    
159
	@Override
160
	public <T extends DefinedTermBase> Pager<T> getIncludes(Collection<T> definedTerms, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
161
        Integer numberOfResults = dao.countIncludes(definedTerms);
162

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

    
168
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
169
	}
170

    
171
	@Override
172
	public Pager<Media> getMedia(DefinedTermBase definedTerm, Integer pageSize,	Integer pageNumber) {
173
        Integer numberOfResults = dao.countMedia(definedTerm);
174

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

    
180
		return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
181
	}
182

    
183
	@Override
184
	public <T extends DefinedTermBase> Pager<T> getPartOf(Set<T> definedTerms,Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
185
        Integer numberOfResults = dao.countPartOf(definedTerms);
186

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

    
192
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
193
	}
194

    
195
	@Override
196
	public Pager<NamedArea> list(NamedAreaLevel level, NamedAreaType type, Integer pageSize, Integer pageNumber,
197
			List<OrderHint> orderHints, List<String> propertyPaths) {
198
		Integer numberOfResults = dao.count(level, type);
199

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

    
205
		return new DefaultPagerImpl<NamedArea>(pageNumber, numberOfResults, pageSize, results);
206
	}
207

    
208
	@Override
209
	public <T extends DefinedTermBase> Pager<T> findByRepresentationText(String label, Class<T> clazz, Integer pageSize, Integer pageNumber) {
210
        Integer numberOfResults = dao.countDefinedTermByRepresentationText(label,clazz);
211

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

    
217
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
218
	}
219

    
220
	@Override
221
	public <T extends DefinedTermBase> Pager<T> findByRepresentationAbbreviation(String abbrev, Class<T> clazz, Integer pageSize, Integer pageNumber) {
222
        Integer numberOfResults = dao.countDefinedTermByRepresentationAbbrev(abbrev,clazz);
223

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

    
229
		return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
230
	}
231

    
232
	@Override
233
	public List<LanguageString> getAllLanguageStrings(int limit, int start) {
234
		return languageStringDao.list(limit, start);
235
	}
236

    
237
	@Override
238
	public List<Representation> getAllRepresentations(int limit, int start) {
239
		return representationDao.list(limit,start);
240
	}
241

    
242
	@Override
243
	public UUID saveLanguageData(LanguageStringBase languageData) {
244
		return languageStringBaseDao.save(languageData).getUuid();
245
	}
246

    
247
	/* (non-Javadoc)
248
	 * @see eu.etaxonomy.cdm.api.service.ServiceBase#delete(eu.etaxonomy.cdm.model.common.CdmBase)
249
	 */
250
	/** @deprecated use {@link #delete(DefinedTermBase, TermDeletionConfigurator)} instead
251
	 * to allow DeleteResult return type*/
252
	@Override
253
	@Deprecated
254
	public DeleteResult delete(DefinedTermBase term){
255
		DeleteResult result = new DeleteResult();
256

    
257
		TermDeletionConfigurator defaultConfig = new TermDeletionConfigurator();
258
		result = delete(term, defaultConfig);
259
		return result;
260
	}
261

    
262
	@Override
263
	@Deprecated
264
	@Transactional(readOnly = false)
265
	public DeleteResult delete(UUID termUuid){
266
	    DeleteResult result = new DeleteResult();
267

    
268
	    TermDeletionConfigurator defaultConfig = new TermDeletionConfigurator();
269
	    result = delete(dao.load(termUuid), defaultConfig);
270
	    return result;
271
	}
272

    
273
	@Override
274
	public DeleteResult delete(DefinedTermBase term, TermDeletionConfigurator config){
275
		if (config == null){
276
			config = new TermDeletionConfigurator();
277
		}
278
//		boolean isInternal = config.isInternal();
279

    
280
		Set<DefinedTermBase> termsToSave = new HashSet<DefinedTermBase>();
281

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

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

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

    
336

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

    
367
			//part of
368
			if (parentTerm != null){
369
				if (config.isDeletePartOfRelations()){
370
					parentTerm.removeIncludes(term);
371
					termsToSave.add(parentTerm);
372
				}else{
373
					//handelede before "included in"
374
				}
375
			}
376

    
377
//			relatedObjects;
378

    
379

    
380
			if (result.isOk()){
381
				TermVocabulary voc = term.getVocabulary();
382
				if (voc!= null){
383
					voc.removeTerm(term);
384
				}
385
				//TODO save voc
386
				if (true /*!config.isInternal()*/){
387
					dao.delete(term);
388
					dao.saveOrUpdateAll(termsToSave);
389
//					for (DeleteResult.PersistPair persistPair : result.getObjectsToDelete()){
390
//						persistPair.dao.delete(persistPair.objectToPersist);
391
//					}
392
//					for (DeleteResult.PersistPair persistPair : result.getObjectsToSave()){
393
//						persistPair.dao.saveOrUpdate(persistPair.objectToPersist);
394
//					}
395

    
396
				}
397
			}
398
		} catch (DataChangeNoRollbackException e) {
399
			result.setStatus(Status.ERROR);
400
		}
401
		return result;
402
	}
403

    
404
	@Override
405
	@Transactional(readOnly = false)
406
	public DeleteResult delete(UUID termUuid, TermDeletionConfigurator config){
407
	    return delete(dao.load(termUuid), config);
408
	}
409

    
410
	@Override
411
	@Transactional(readOnly = false)
412
    public void updateTitleCache(Class<? extends DefinedTermBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DefinedTermBase> cacheStrategy, IProgressMonitor monitor) {
413
		//TODO shouldnt this be TermBase instead of DefinedTermBase
414
		if (clazz == null){
415
			clazz = DefinedTermBase.class;
416
		}
417
		super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
418
	}
419

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

    
434
                    String message = "An object of " + ref.getClass().getName() + " with ID " + ref.getId() + " is referencing the object" ;
435
                    result.addException(new ReferencedObjectUndeletableException(message));
436
                    result.setAbort();
437
                }
438

    
439
            }
440
        }
441
        return result;
442
    }
443

    
444
}
(91-91/97)