X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/e0dbe59ad20308e0b68c8ec46c466781d710ebd4..ca3c7088bd59b1444a83b581eb37919b1b73fe24:/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TermServiceImpl.java diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TermServiceImpl.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TermServiceImpl.java index 43562b383f..ab79534fd3 100644 --- a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TermServiceImpl.java +++ b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TermServiceImpl.java @@ -1,364 +1,444 @@ // $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 implements ITermService{ +public class TermServiceImpl extends IdentifiableServiceBase 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 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 terms) - */ - @Transactional(readOnly = false) - public Map saveTermsAll(Collection 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> getVocabulary(UUID vocabularyUuid) { - TermVocabulary> vocabulary = (TermVocabulary) vocabularyDao.findByUuid(vocabularyUuid); - return vocabulary; - } - - /** - * FIXME candidate for harmonization - * vocabularyService.load - */ - public TermVocabulary loadVocabulary(UUID vocabularyUuid, List propertyPaths) { - TermVocabulary> vocabulary = (TermVocabulary) vocabularyDao.load(vocabularyUuid, - propertyPaths); - return vocabulary; - } - - /** - * FIXME candidate for harmonization - * move to vocabularyService - */ - public TermVocabulary> getVocabulary(VocabularyEnum vocabularyType){ - TermVocabulary> 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 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> getAllTermVocabularies(int limit, int start) { - return vocabularyDao.list(limit, start); - } - - public List> listTermVocabularies(Integer limit, Integer start, List orderHints, - List propertyPaths){ - return vocabularyDao.list(limit, start, orderHints, propertyPaths); + @Override + public List listByTermType(TermType termType, Integer limit, Integer start, + List orderHints, List propertyPaths) { + return dao.listByTermType(termType, limit, start, orderHints, propertyPaths); } - /** - * FIXME candidate for harmonization - * vocabularyService.page - */ - public Pager> pageTermVocabularies(Integer pageSize, Integer pageNumber, - List orderHints, List propertyPaths) { - - List> vocabs = vocabularyDao.list(pageSize, pageNumber * pageSize, orderHints, - propertyPaths); - Pager> pager = new DefaultPagerImpl>( - 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 getLanguageVocabulary() { - String uuidString = "45ac7043-7f5e-4f37-92f2-3874aaaef2de"; - UUID uuid = UUID.fromString(uuidString); - TermVocabulary languageVocabulary = - (TermVocabulary)vocabularyDao.findByUuid(uuid); - return languageVocabulary; - } - - /** - * FIXME candidate for harmonization - * vocabularyService.save(Set vocabularies) - */ - public Map> - saveTermVocabulariesAll(Collection> 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 saveRepresentationsAll(Collection representations){ -// return representationDao.saveAll(representations); -// } - - /** - * FIXME candidate for harmonization - * this code is not used, remove it - */ - @Transactional(readOnly = false) - public Map saveLanguageDataAll(Collection 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 saveRepresentationAll(Collection representations) { - return representationDao.saveAll(representations); - } - - /** - * FIXME candidate for harmonization - * Given that representations are owned by TermBase, this method is redundant - */ - public List 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 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 - saveLanguageStringBasesAll(Collection 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 getLanguagesByLocale(Enumeration 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 findByIdInVocabulary(String id, UUID vocabularyUuid, Class clazz) throws IllegalArgumentException { + List 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 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 Pager getGeneralizationOf(T definedTerm, Integer pageSize, Integer pageNumber) { Integer numberOfResults = dao.countGeneralizationOf(definedTerm); - + List results = new ArrayList(); - 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(pageNumber, numberOfResults, pageSize, results); } - public Pager getIncludes(Set definedTerms, Integer pageSize, Integer pageNumber, List propertyPaths) { + @Override + public Pager getIncludes(Collection definedTerms, Integer pageSize, Integer pageNumber, List propertyPaths) { Integer numberOfResults = dao.countIncludes(definedTerms); - + List results = new ArrayList(); - 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(pageNumber, numberOfResults, pageSize, results); } + @Override public Pager getMedia(DefinedTermBase definedTerm, Integer pageSize, Integer pageNumber) { Integer numberOfResults = dao.countMedia(definedTerm); - + List results = new ArrayList(); - 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(pageNumber, numberOfResults, pageSize, results); } + @Override public Pager getPartOf(Set definedTerms,Integer pageSize, Integer pageNumber, List propertyPaths) { Integer numberOfResults = dao.countPartOf(definedTerms); - + List results = new ArrayList(); - 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(pageNumber, numberOfResults, pageSize, results); } + @Override public Pager list(NamedAreaLevel level, NamedAreaType type, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { Integer numberOfResults = dao.count(level, type); List results = new ArrayList(); - 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(pageNumber, numberOfResults, pageSize, results); } + @Override public Pager findByRepresentationText(String label, Class clazz, Integer pageSize, Integer pageNumber) { Integer numberOfResults = dao.countDefinedTermByRepresentationText(label,clazz); - + List results = new ArrayList(); - 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(pageNumber, numberOfResults, pageSize, results); + } + + @Override + public Pager findByRepresentationAbbreviation(String abbrev, Class clazz, Integer pageSize, Integer pageNumber) { + Integer numberOfResults = dao.countDefinedTermByRepresentationAbbrev(abbrev,clazz); + + List results = new ArrayList(); + if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) + results = dao.getDefinedTermByRepresentationAbbrev(abbrev, clazz, pageSize, pageNumber); + } + return new DefaultPagerImpl(pageNumber, numberOfResults, pageSize, results); - } + } + + @Override + public List getAllLanguageStrings(int limit, int start) { + return languageStringDao.list(limit, start); + } + + @Override + public List 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 termsToSave = new HashSet(); + + DeleteResult result = isDeletable(term, config); + //CdmBase.deproxy(dao.merge(term), DefinedTermBase.class); + try { + //generalization of + Set 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 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 clazz, Integer stepSize, IIdentifiableEntityCacheStrategy 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 references = commonService.getReferencingObjectsForDeletion(term); + if (references != null){ + result.addRelatedObjects(references); + Iterator 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; + } + }