Fix specimen retrieval by assignment status
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / TermServiceImpl.java
index 43562b383fe42336ef670430a1f4d6e914e6606d..ab79534fd3eff37adc1bb7b36924f7682a572183 100644 (file)
 // $Id$
 /**
 * Copyright (C) 2007 EDIT
-* European Distributed Institute of Taxonomy 
+* European Distributed Institute of Taxonomy
 * http://www.e-taxonomy.eu
-* 
+*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * See LICENSE.TXT at the top of this package for the full license terms.
 */
 
 package eu.etaxonomy.cdm.api.service;
 
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import eu.etaxonomy.cdm.api.service.UpdateResult.Status;
+import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;
+import eu.etaxonomy.cdm.api.service.config.TermDeletionConfigurator;
+import eu.etaxonomy.cdm.api.service.exception.DataChangeNoRollbackException;
+import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
 import eu.etaxonomy.cdm.api.service.pager.Pager;
 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
+import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
+import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
 import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.LanguageString;
 import eu.etaxonomy.cdm.model.common.LanguageStringBase;
-import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
 import eu.etaxonomy.cdm.model.common.Representation;
+import eu.etaxonomy.cdm.model.common.TermType;
 import eu.etaxonomy.cdm.model.common.TermVocabulary;
-import eu.etaxonomy.cdm.model.common.VocabularyEnum;
 import eu.etaxonomy.cdm.model.location.NamedArea;
 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
 import eu.etaxonomy.cdm.model.location.NamedAreaType;
-import eu.etaxonomy.cdm.model.location.TdwgArea;
 import eu.etaxonomy.cdm.model.media.Media;
-import eu.etaxonomy.cdm.model.name.NameRelationship;
 import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
 import eu.etaxonomy.cdm.persistence.dao.common.ILanguageStringBaseDao;
 import eu.etaxonomy.cdm.persistence.dao.common.ILanguageStringDao;
 import eu.etaxonomy.cdm.persistence.dao.common.IRepresentationDao;
-import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
 import eu.etaxonomy.cdm.persistence.query.OrderHint;
+import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
 
 @Service
 @Transactional(readOnly = true)
-public class TermServiceImpl extends ServiceBase<DefinedTermBase,IDefinedTermDao> implements ITermService{
+public class TermServiceImpl extends IdentifiableServiceBase<DefinedTermBase,IDefinedTermDao> implements ITermService{
+       @SuppressWarnings("unused")
        private static final Logger logger = Logger.getLogger(TermServiceImpl.class);
-       
-       protected ITermVocabularyDao vocabularyDao;
+
+       private ILanguageStringDao languageStringDao;
+
        @Autowired
        @Qualifier("langStrBaseDao")
        private ILanguageStringBaseDao languageStringBaseDao;
-       @Autowired
        private IRepresentationDao representationDao;
+
        @Autowired
-       private ILanguageStringDao languageStringDao;
-       
-       @Autowired
-       protected void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
-               this.vocabularyDao = vocabularyDao;
-       }
-       
-       /**
-        *  (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.ITermService#getTermByUri(java.lang.String)
-        * FIXME Candidate for harmonization
-        * rename -> getByUri
-        */
-       public DefinedTermBase getTermByUri(String uri) {
-               //FIXME transformation from URI to UUID
-               return dao.findByUri(uri);
-       }
-       
-       /**
-        *  (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.ITermService#getTermByUuid(java.util.UUID)
-        * FIXME candidate for harmonization
-        */
-       public DefinedTermBase getTermByUuid(UUID uuid) {
-               return dao.findByUuid(uuid);  
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * list
-        */
-       public List<DefinedTermBase> getAllDefinedTerms(int limit, int start){
-               return dao.list(limit, start);
+       public void setLanguageStringDao(ILanguageStringDao languageStringDao) {
+               this.languageStringDao = languageStringDao;
        }
 
-       /**
-        * FIXME candidate for harmonization
-        * save
-        */
-       @Transactional(readOnly = false)
-       public UUID saveTerm(DefinedTermBase termBase) {
-               return super.saveCdmObject(termBase);
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * save(Set<DefinedTermBase> terms)
-        */
-       @Transactional(readOnly = false)
-       public Map<UUID, DefinedTermBase> saveTermsAll(Collection<? extends DefinedTermBase> termBaseCollection){
-               return saveCdmObjectAll(termBaseCollection);
+       @Autowired
+       public void setRepresentationDao(IRepresentationDao representationDao) {
+               this.representationDao = representationDao;
        }
 
-       /**
-        *  (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.ITermService#getVocabulary(java.util.UUID)
-        * FIXME candidate for harmonization
-        * vocabuaryService.find
-        */
-       public TermVocabulary<? extends DefinedTermBase<?>> getVocabulary(UUID vocabularyUuid) {
-               TermVocabulary<? extends DefinedTermBase<?>> vocabulary = (TermVocabulary) vocabularyDao.findByUuid(vocabularyUuid);
-               return vocabulary;
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * vocabularyService.load
-        */
-       public TermVocabulary loadVocabulary(UUID vocabularyUuid, List<String> propertyPaths) {
-               TermVocabulary<? extends DefinedTermBase<?>> vocabulary = (TermVocabulary) vocabularyDao.load(vocabularyUuid,
-                       propertyPaths);
-               return vocabulary;
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * move to vocabularyService
-        */
-       public TermVocabulary<? extends DefinedTermBase<?>> getVocabulary(VocabularyEnum vocabularyType){
-               TermVocabulary<? extends DefinedTermBase<?>> vocabulary = getVocabulary(vocabularyType.getUuid());
-               return vocabulary;
-       }
-       
-       /**
-        *  (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.ITermService#listVocabularies(java.lang.Class)
-        * FIXME candidate for harmonization
-        * vocabularyService.list
-        */
-       public Set<TermVocabulary> listVocabularies(Class termClass) {
-               logger.error("Method not implemented yet");
-               return null;
+       @Override
+    @Autowired
+       protected void setDao(IDefinedTermDao dao) {
+               this.dao = dao;
        }
 
-       /**
-        * FIXME candidate for harmonization
-        * vocabularyService.list
+       /* (non-Javadoc)
+        * @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)
         */
-       public List<TermVocabulary<DefinedTermBase>> getAllTermVocabularies(int limit, int start) {
-               return vocabularyDao.list(limit, start);
-       }
-       
-       public List<TermVocabulary<DefinedTermBase>> listTermVocabularies(Integer limit, Integer start, List<OrderHint> orderHints,
-               List<String> propertyPaths){
-               return vocabularyDao.list(limit, start, orderHints, propertyPaths);
+       @Override
+       public <T extends DefinedTermBase> List<T> listByTermType(TermType termType, Integer limit, Integer start,
+               List<OrderHint> orderHints, List<String> propertyPaths) {
+           return dao.listByTermType(termType, limit, start, orderHints, propertyPaths);
        }
 
-       /**
-        * FIXME candidate for harmonization
-        * vocabularyService.page
-        */
-       public Pager<TermVocabulary<DefinedTermBase>> pageTermVocabularies(Integer pageSize, Integer pageNumber,
-                       List<OrderHint> orderHints, List<String> propertyPaths) {
-
-               List<TermVocabulary<DefinedTermBase>> vocabs = vocabularyDao.list(pageSize, pageNumber * pageSize, orderHints,
-                       propertyPaths);
-               Pager<TermVocabulary<DefinedTermBase>> pager = new DefaultPagerImpl<TermVocabulary<DefinedTermBase>>(
-                       pageNumber, vocabs.size(), pageSize, vocabs);
-               return pager;
-       }
-       
-       /** 
-        * (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.ITermService#getLanguageVocabulary()
-        * FIXME candidate for harmonization
-        * is this the same as getVocabulary(VocabularyEnum.Language)
-        */
-       public TermVocabulary<Language> getLanguageVocabulary() {
-               String uuidString = "45ac7043-7f5e-4f37-92f2-3874aaaef2de";
-               UUID uuid = UUID.fromString(uuidString);
-               TermVocabulary<Language> languageVocabulary = 
-                       (TermVocabulary)vocabularyDao.findByUuid(uuid);
-               return languageVocabulary;
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * vocabularyService.save(Set<TermVocabulary> vocabularies)
-        */
-       public Map<UUID, TermVocabulary<DefinedTermBase>> 
-    saveTermVocabulariesAll(Collection<TermVocabulary<DefinedTermBase>> termVocabularies) {
-               return vocabularyDao.saveAll(termVocabularies);
-       }
-       
-       public UUID saveTermVocabulary(TermVocabulary termVocabulary) {
-               return vocabularyDao.save(termVocabulary);
+       @Override
+       public DefinedTermBase getByUri(URI uri) {
+               return dao.findByUri(uri);
        }
 
-       /**
-        * FIXME candidate for harmonization
-        * remove redundant code
-        */
-//     @Transactional(readOnly = false)
-//     public Map<UUID, Representation> saveRepresentationsAll(Collection<Representation> representations){
-//             return representationDao.saveAll(representations);
-//     }
-
-       /**
-        * FIXME candidate for harmonization
-        * this code is not used, remove it
-        */
-       @Transactional(readOnly = false)
-       public Map<UUID, LanguageStringBase> saveLanguageDataAll(Collection<LanguageStringBase> languageData) {
-               return languageStringBaseDao.saveAll(languageData);
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * Given that representations are owned by TermBase, this method is redundant
-        * @param representations
-        * @return
-        */
-       @Transactional(readOnly = false)
-       public Map<UUID, Representation> saveRepresentationAll(Collection<Representation> representations) {
-               return representationDao.saveAll(representations);
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * Given that representations are owned by TermBase, this method is redundant
-        */
-       public List<Representation> getAllRepresentations(int limit, int start){
-               return representationDao.list(limit, start);
+       @Override
+       public Language getLanguageByIso(String iso639) {
+           return dao.getLanguageByIso(iso639);
        }
 
-       /**
-        * FIXME candidate for harmonization
-        * Given that languageStrings are owned by other objects, this method is redundant
-        */
-       public List<LanguageString> getAllLanguageStrings(int limit, int start) {
-               return languageStringDao.list(limit, start);
-       }
-       
-       /**
-        * FIXME candidate for harmonization
-        * Given that languageStrings are owned by other objects, this method is redundant
-        */
-       public Map<UUID, LanguageStringBase> 
-              saveLanguageStringBasesAll(Collection<LanguageStringBase> languageStringBases) {
-               return languageStringBaseDao.saveAll(languageStringBases);
-       }
-       
-       public Language getLanguageByIso(String iso639) {
-               return dao.getLanguageByIso(iso639);
+       @Override
+       public Language getLanguageByLabel(String label) {
+           return Language.getLanguageByLabel(label);
        }
-       
+
+       @Override
        public List<Language> getLanguagesByLocale(Enumeration<Locale> locales){
                return dao.getLanguagesByLocale(locales);
        }
-       
-       /**
-        * FIXME candidate for harmonization
-        * Given that languageStrings are owned by other objects, this method is redundant
-        */
-       @Transactional(readOnly = false)
-       public UUID saveLanguageData(
-                       LanguageStringBase languageData) {
-                       return languageStringBaseDao.save(languageData);
-       }
 
-       @Autowired
-       protected void setDao(IDefinedTermDao dao) {
-               this.dao = dao;
+       @Override
+    public <TERM extends DefinedTermBase> TERM findByIdInVocabulary(String id, UUID vocabularyUuid, Class<TERM> clazz) throws IllegalArgumentException {
+        List<TERM> list = dao.getDefinedTermByIdInVocabulary(id, vocabularyUuid, clazz, null, null);
+               if (list.isEmpty()){
+                       return null;
+               }else if (list.size() == 1){
+                       return list.get(0);
+               }else{
+                       String message = "There is more then 1 (%d) term with the same id in vocabulary. This is forbidden. Check the state of your database.";
+                       throw new IllegalStateException(String.format(message, list.size()));
+               }
        }
 
-       /**
-        *  (non-Javadoc)
-        * @see eu.etaxonomy.cdm.api.service.ITermService#getAreaByTdwgAbbreviation(java.lang.String)
-        */
+
+       @Override
        public NamedArea getAreaByTdwgAbbreviation(String tdwgAbbreviation) {
-               //FIXME this is just a placeholder until it is decided where to implement this method 
-               //(see also FIXMEs in TdwgArea)
-               return TdwgArea.getAreaByTdwgAbbreviation(tdwgAbbreviation);
+               if (StringUtils.isBlank(tdwgAbbreviation)){ //TDWG areas should always have a label
+                       return null;
+               }
+               List<NamedArea> list = dao.getDefinedTermByIdInVocabulary(tdwgAbbreviation, NamedArea.uuidTdwgAreaVocabulary, NamedArea.class, null, null);
+               if (list.isEmpty()){
+                       return null;
+               }else if (list.size() == 1){
+                       return list.get(0);
+               }else{
+                       String message = "There is more then 1 (%d) TDWG area with the same abbreviated label. This is forbidden. Check the state of your database.";
+                       throw new IllegalStateException(String.format(message, list.size()));
+               }
+
        }
 
+       @Override
        public <T extends DefinedTermBase> Pager<T> getGeneralizationOf(T definedTerm, Integer pageSize, Integer pageNumber) {
         Integer numberOfResults = dao.countGeneralizationOf(definedTerm);
-               
+
                List<T> results = new ArrayList<T>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.getGeneralizationOf(definedTerm, pageSize, pageNumber); 
+               if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+                       results = dao.getGeneralizationOf(definedTerm, pageSize, pageNumber);
                }
-               
+
                return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
        }
 
-       public <T extends DefinedTermBase> Pager<T> getIncludes(Set<T> definedTerms, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+       @Override
+       public <T extends DefinedTermBase> Pager<T> getIncludes(Collection<T> definedTerms, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
         Integer numberOfResults = dao.countIncludes(definedTerms);
-               
+
                List<T> results = new ArrayList<T>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.getIncludes(definedTerms, pageSize, pageNumber,propertyPaths); 
+               if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+                       results = dao.getIncludes(definedTerms, pageSize, pageNumber,propertyPaths);
                }
-               
+
                return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
        }
 
+       @Override
        public Pager<Media> getMedia(DefinedTermBase definedTerm, Integer pageSize,     Integer pageNumber) {
         Integer numberOfResults = dao.countMedia(definedTerm);
-               
+
                List<Media> results = new ArrayList<Media>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.getMedia(definedTerm, pageSize, pageNumber); 
+               if(numberOfResults > 0) { // no point checking again  //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+                       results = dao.getMedia(definedTerm, pageSize, pageNumber);
                }
-               
+
                return new DefaultPagerImpl<Media>(pageNumber, numberOfResults, pageSize, results);
        }
 
+       @Override
        public <T extends DefinedTermBase> Pager<T> getPartOf(Set<T> definedTerms,Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
         Integer numberOfResults = dao.countPartOf(definedTerms);
-               
+
                List<T> results = new ArrayList<T>();
-               if(numberOfResults > 0) { // no point checking again
-                       results = dao.getPartOf(definedTerms, pageSize, pageNumber, propertyPaths); 
+               if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+                       results = dao.getPartOf(definedTerms, pageSize, pageNumber, propertyPaths);
                }
-               
+
                return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
        }
 
+       @Override
        public Pager<NamedArea> list(NamedAreaLevel level, NamedAreaType type, Integer pageSize, Integer pageNumber,
                        List<OrderHint> orderHints, List<String> propertyPaths) {
                Integer numberOfResults = dao.count(level, type);
 
                List<NamedArea> results = new ArrayList<NamedArea>();
-               if (numberOfResults > 0) { // no point checking again
+               if (numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
                        results = dao.list(level, type, pageSize, pageNumber, orderHints, propertyPaths);
                }
 
                return new DefaultPagerImpl<NamedArea>(pageNumber, numberOfResults, pageSize, results);
        }
 
+       @Override
        public <T extends DefinedTermBase> Pager<T> findByRepresentationText(String label, Class<T> clazz, Integer pageSize, Integer pageNumber) {
         Integer numberOfResults = dao.countDefinedTermByRepresentationText(label,clazz);
-               
+
                List<T> results = new ArrayList<T>();
-               if(numberOfResults > 0) { // no point checking again
+               if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
                        results = dao.getDefinedTermByRepresentationText(label, clazz, pageSize, pageNumber);
                }
-               
+
+               return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
+       }
+
+       @Override
+       public <T extends DefinedTermBase> Pager<T> findByRepresentationAbbreviation(String abbrev, Class<T> clazz, Integer pageSize, Integer pageNumber) {
+        Integer numberOfResults = dao.countDefinedTermByRepresentationAbbrev(abbrev,clazz);
+
+               List<T> results = new ArrayList<T>();
+               if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
+                       results = dao.getDefinedTermByRepresentationAbbrev(abbrev, clazz, pageSize, pageNumber);
+               }
+
                return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
-       }       
+       }
+
+       @Override
+       public List<LanguageString> getAllLanguageStrings(int limit, int start) {
+               return languageStringDao.list(limit, start);
+       }
+
+       @Override
+       public List<Representation> getAllRepresentations(int limit, int start) {
+               return representationDao.list(limit,start);
+       }
+
+       @Override
+       public UUID saveLanguageData(LanguageStringBase languageData) {
+               return languageStringBaseDao.save(languageData).getUuid();
+       }
+
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.api.service.ServiceBase#delete(eu.etaxonomy.cdm.model.common.CdmBase)
+        */
+       /** @deprecated use {@link #delete(DefinedTermBase, TermDeletionConfigurator)} instead
+        * to allow DeleteResult return type*/
+       @Override
+       @Deprecated
+       public DeleteResult delete(DefinedTermBase term){
+               DeleteResult result = new DeleteResult();
+
+               TermDeletionConfigurator defaultConfig = new TermDeletionConfigurator();
+               result = delete(term, defaultConfig);
+               return result;
+       }
+
+       @Override
+       @Deprecated
+       @Transactional(readOnly = false)
+       public DeleteResult delete(UUID termUuid){
+           DeleteResult result = new DeleteResult();
+
+           TermDeletionConfigurator defaultConfig = new TermDeletionConfigurator();
+           result = delete(dao.load(termUuid), defaultConfig);
+           return result;
+       }
+
+       @Override
+       public DeleteResult delete(DefinedTermBase term, TermDeletionConfigurator config){
+               if (config == null){
+                       config = new TermDeletionConfigurator();
+               }
+//             boolean isInternal = config.isInternal();
+
+               Set<DefinedTermBase> termsToSave = new HashSet<DefinedTermBase>();
+
+               DeleteResult result = isDeletable(term, config);
+               //CdmBase.deproxy(dao.merge(term), DefinedTermBase.class);
+               try {
+                       //generalization of
+                       Set<DefinedTermBase> specificTerms = term.getGeneralizationOf();
+                       if (specificTerms.size()>0){
+                               if (config.isDeleteGeneralizationOfRelations()){
+                                       DefinedTermBase generalTerm = term.getKindOf();
+                                       for (DefinedTermBase specificTerm: specificTerms){
+                                               term.removeGeneralization(specificTerm);
+                                               if (generalTerm != null){
+                                                       generalTerm.addGeneralizationOf(specificTerm);
+                                                       termsToSave.add(generalTerm);
+                                               }
+                                       }
+                               }else{
+                                       //TODO Exception type
+                                       String message = "This term has specifing terms. Move or delete specifiing terms prior to delete or change delete configuration.";
+                                       result.addRelatedObjects(specificTerms);
+                                       result.setAbort();
+                                       Exception ex = new DataChangeNoRollbackException(message);
+                                       result.addException(ex);
+                               }
+                       }
+
+                       //kind of
+                       DefinedTermBase generalTerm = term.getKindOf();
+                       if (generalTerm != null){
+                               if (config.isDeleteKindOfRelations()){
+                                       generalTerm.removeGeneralization(term);
+                               }else{
+                                       //TODO Exception type
+                                       String message = "This term is kind of another term. Move or delete kind of relationship prior to delete or change delete configuration.";
+                                       result.addRelatedObject(generalTerm);
+                                       result.setAbort();
+                                       DataChangeNoRollbackException ex = new DataChangeNoRollbackException(message);
+                                       result.addException(ex);
+                                       throw ex;
+                               }
+                       }
+
+                       //part of
+                       DefinedTermBase parentTerm = term.getPartOf();
+                       if (parentTerm != null){
+                               if (! config.isDeletePartOfRelations()){
+                                       //TODO Exception type
+                                       String message = "This term is included in another term. Remove from parent term prior to delete or change delete configuration.";
+                                       result.addRelatedObject(parentTerm);
+                                       result.setAbort();
+                                       DataChangeNoRollbackException ex = new DataChangeNoRollbackException(message);
+                                       result.addException(ex);
+                               }
+                       }
+
+
+                       //included in
+                       Set<DefinedTermBase> includedTerms = term.getIncludes();
+                       if (includedTerms.size()> 0){
+//                             if (config.isDeleteIncludedTerms()){
+//                                     for (DefinedTermBase includedTerm: includedTerms){
+//                                             config.setCheck(true);
+//                                             DeleteResult includedResult = this.delete(includedTerm, config);
+////                                           config.setCheck(isCheck);
+//                                             result.includeResult(includedResult);
+//                                     }
+//                             }else
+                                       if (config.isDeleteIncludedRelations()){
+                                       DefinedTermBase parent = term.getPartOf();
+                                       for (DefinedTermBase includedTerm: includedTerms){
+                                               term.removeIncludes(includedTerm);
+                                               if (parent != null){
+                                                       parent.addIncludes(includedTerm);
+                                                       termsToSave.add(parent);
+                                               }
+                                       }
+                               }else{
+                                       //TODO Exception type
+                                       String message = "This term includes other terms. Move or delete included terms prior to delete or change delete configuration.";
+                                       result.addRelatedObjects(includedTerms);
+                                       result.setAbort();
+                                       Exception ex = new DataChangeNoRollbackException(message);
+                                       result.addException(ex);
+                               }
+                       }
+
+                       //part of
+                       if (parentTerm != null){
+                               if (config.isDeletePartOfRelations()){
+                                       parentTerm.removeIncludes(term);
+                                       termsToSave.add(parentTerm);
+                               }else{
+                                       //handelede before "included in"
+                               }
+                       }
+
+//                     relatedObjects;
+
+
+                       if (result.isOk()){
+                               TermVocabulary voc = term.getVocabulary();
+                               if (voc!= null){
+                                       voc.removeTerm(term);
+                               }
+                               //TODO save voc
+                               if (true /*!config.isInternal()*/){
+                                       dao.delete(term);
+                                       dao.saveOrUpdateAll(termsToSave);
+//                                     for (DeleteResult.PersistPair persistPair : result.getObjectsToDelete()){
+//                                             persistPair.dao.delete(persistPair.objectToPersist);
+//                                     }
+//                                     for (DeleteResult.PersistPair persistPair : result.getObjectsToSave()){
+//                                             persistPair.dao.saveOrUpdate(persistPair.objectToPersist);
+//                                     }
+
+                               }
+                       }
+               } catch (DataChangeNoRollbackException e) {
+                       result.setStatus(Status.ERROR);
+               }
+               return result;
+       }
+
+       @Override
+       @Transactional(readOnly = false)
+       public DeleteResult delete(UUID termUuid, TermDeletionConfigurator config){
+           return delete(dao.load(termUuid), config);
+       }
+
+       @Override
+       @Transactional(readOnly = false)
+    public void updateTitleCache(Class<? extends DefinedTermBase> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<DefinedTermBase> cacheStrategy, IProgressMonitor monitor) {
+               //TODO shouldnt this be TermBase instead of DefinedTermBase
+               if (clazz == null){
+                       clazz = DefinedTermBase.class;
+               }
+               super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
+       }
+
+       @Override
+    public DeleteResult isDeletable(DefinedTermBase term, DeleteConfiguratorBase config){
+        DeleteResult result = new DeleteResult();
+        Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(term);
+        if (references != null){
+            result.addRelatedObjects(references);
+            Iterator<CdmBase> iterator = references.iterator();
+            CdmBase ref;
+            while (iterator.hasNext()){
+                ref = iterator.next();
+                if (ref instanceof TermVocabulary){
+                    result.getRelatedObjects().remove(ref);
+                }else{
+
+                    String message = "An object of " + ref.getClass().getName() + " with ID " + ref.getId() + " is referencing the object" ;
+                    result.addException(new ReferencedObjectUndeletableException(message));
+                    result.setAbort();
+                }
+
+            }
+        }
+        return result;
+    }
+
 }