Project

General

Profile

Download (16.9 KB) Statistics
| Branch: | Tag: | Revision:
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

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

    
12
import java.net.URI;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Enumeration;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Locale;
20
import java.util.Map;
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.TermBase;
46
import eu.etaxonomy.cdm.model.common.TermType;
47
import eu.etaxonomy.cdm.model.common.TermVocabulary;
48
import eu.etaxonomy.cdm.model.location.NamedArea;
49
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
50
import eu.etaxonomy.cdm.model.location.NamedAreaType;
51
import eu.etaxonomy.cdm.model.media.Media;
52
import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
53
import eu.etaxonomy.cdm.persistence.dao.common.ILanguageStringBaseDao;
54
import eu.etaxonomy.cdm.persistence.dao.common.ILanguageStringDao;
55
import eu.etaxonomy.cdm.persistence.dao.common.IRepresentationDao;
56
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
57
import eu.etaxonomy.cdm.persistence.query.OrderHint;
58
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
59

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

    
66
	private ILanguageStringDao languageStringDao;
67

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

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

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

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

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

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

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

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

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

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

    
128

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
245

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

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

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

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

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

    
276
		Set<DefinedTermBase> termsToSave = new HashSet<DefinedTermBase>();
277

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

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

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

    
332

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

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

    
373
//			relatedObjects;
374

    
375

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

    
393
				}
394
			}
395
		} catch (DataChangeNoRollbackException e) {
396
			result.setStatus(Status.ERROR);
397
		}
398
		return result;
399
	}
400

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

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

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

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

    
437
            }
438
        }
439
        return result;
440
    }
441

    
442
    @Override
443
    @Transactional(readOnly = false)
444
    public Map<UUID, Representation> saveOrUpdateRepresentations(Collection<Representation> representations){
445
        return representationDao.saveOrUpdateAll(representations);
446
    }
447

    
448
    @Override
449
    @Transactional(readOnly = true)
450
    public List<UuidAndTitleCache<NamedArea>> getUuidAndTitleCache(List<TermVocabulary> vocs, Integer limit, String pattern, Language lang) {
451
        List<NamedArea> areas = dao.getUuidAndTitleCache(vocs, limit, pattern);
452

    
453
        List<UuidAndTitleCache<NamedArea>> result = new ArrayList();
454
        UuidAndTitleCache<NamedArea> uuidAndTitleCache;
455
        for (NamedArea area: areas){
456
            uuidAndTitleCache = new UuidAndTitleCache<>(area.getUuid(), area.getId(), area.labelWithLevel(area, lang));
457
            result.add(uuidAndTitleCache);
458
        }
459

    
460
        return result;
461
    }
462

    
463

    
464
}
(100-100/105)