import java.util.EnumSet;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
+import java.util.Iterator;\r
import java.util.List;\r
import java.util.Map;\r
import java.util.Set;\r
import java.util.UUID;\r
\r
+import javax.persistence.EntityNotFoundException;\r
+\r
import org.apache.log4j.Logger;\r
import org.apache.lucene.index.CorruptIndexException;\r
import org.apache.lucene.queryParser.ParseException;\r
import org.springframework.stereotype.Service;\r
import org.springframework.transaction.annotation.Transactional;\r
\r
+import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;\r
import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.IncludedTaxonConfiguration;\r
import eu.etaxonomy.cdm.api.service.config.MatchingTaxonConfigurator;\r
-import eu.etaxonomy.cdm.api.service.config.NameDeletionConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.SynonymDeletionConfigurator;\r
import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.TaxonNodeDeletionConfigurator.ChildHandling;\r
+import eu.etaxonomy.cdm.api.service.dto.FindByIdentifierDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.IncludedTaxaDTO;\r
import eu.etaxonomy.cdm.api.service.exception.DataChangeNoRollbackException;\r
import eu.etaxonomy.cdm.api.service.exception.HomotypicalGroupChangeException;\r
import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;\r
import eu.etaxonomy.cdm.api.service.pager.Pager;\r
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;\r
-import eu.etaxonomy.cdm.api.service.search.DocIdBitSetPrinter;\r
import eu.etaxonomy.cdm.api.service.search.ILuceneIndexToolProvider;\r
import eu.etaxonomy.cdm.api.service.search.ISearchResultBuilder;\r
import eu.etaxonomy.cdm.api.service.search.LuceneMultiSearch;\r
import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge;\r
import eu.etaxonomy.cdm.model.CdmBaseType;\r
import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.model.common.DefinedTerm;\r
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
import eu.etaxonomy.cdm.model.common.Language;\r
import eu.etaxonomy.cdm.model.description.Feature;\r
import eu.etaxonomy.cdm.model.description.IIdentificationKey;\r
import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
-import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;\r
+import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;\r
import eu.etaxonomy.cdm.model.description.SpecimenDescription;\r
import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
import eu.etaxonomy.cdm.model.description.TaxonInteraction;\r
import eu.etaxonomy.cdm.model.media.Media;\r
import eu.etaxonomy.cdm.model.media.MediaRepresentation;\r
import eu.etaxonomy.cdm.model.media.MediaUtils;\r
-import eu.etaxonomy.cdm.model.molecular.Amplification;\r
+import eu.etaxonomy.cdm.model.molecular.AmplificationResult;\r
import eu.etaxonomy.cdm.model.molecular.DnaSample;\r
import eu.etaxonomy.cdm.model.molecular.Sequence;\r
import eu.etaxonomy.cdm.model.molecular.SingleRead;\r
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;\r
+import eu.etaxonomy.cdm.model.name.NameRelationship;\r
import eu.etaxonomy.cdm.model.name.Rank;\r
import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
import eu.etaxonomy.cdm.model.name.ZoologicalName;\r
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
+import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;\r
import eu.etaxonomy.cdm.model.reference.Reference;\r
import eu.etaxonomy.cdm.model.taxon.Classification;\r
+import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;\r
import eu.etaxonomy.cdm.model.taxon.Synonym;\r
import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;\r
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;\r
import eu.etaxonomy.cdm.model.taxon.TaxonNode;\r
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;\r
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;\r
-import eu.etaxonomy.cdm.persistence.dao.AbstractBeanInitializer;\r
import eu.etaxonomy.cdm.persistence.dao.common.ICdmGenericDao;\r
import eu.etaxonomy.cdm.persistence.dao.common.IOrderedTermVocabularyDao;\r
+import eu.etaxonomy.cdm.persistence.dao.initializer.AbstractBeanInitializer;\r
import eu.etaxonomy.cdm.persistence.dao.name.ITaxonNameDao;\r
import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;\r
+import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;\r
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;\r
import eu.etaxonomy.cdm.persistence.fetch.CdmFetch;\r
import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
@Autowired\r
private INameService nameService;\r
\r
+ @Autowired\r
+ private ITaxonNodeService nodeService;\r
+\r
@Autowired\r
private ICdmGenericDao genericDao;\r
\r
@Autowired\r
private IOccurrenceDao occurrenceDao;\r
\r
+ @Autowired\r
+ private IClassificationDao classificationDao;\r
+\r
@Autowired\r
private AbstractBeanInitializer beanInitializer;\r
\r
@Autowired\r
private ILuceneIndexToolProvider luceneIndexToolProvider;\r
\r
-\r
/**\r
* Constructor\r
*/\r
return dao.getTaxaByName(name, sec);\r
}\r
\r
- /**\r
- * FIXME Candidate for harmonization\r
- * list(Synonym.class, ...)\r
- * (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllSynonyms(int, int)\r
- */\r
- @Override\r
- public List<Synonym> getAllSynonyms(int limit, int start) {\r
- return dao.getAllSynonyms(limit, start);\r
- }\r
-\r
- /**\r
- * FIXME Candidate for harmonization\r
- * list(Taxon.class, ...)\r
- * (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllTaxa(int, int)\r
- */\r
- @Override\r
- public List<Taxon> getAllTaxa(int limit, int start) {\r
- return dao.getAllTaxa(limit, start);\r
- }\r
-\r
/**\r
* FIXME Candidate for harmonization\r
* merge with getRootTaxa(Reference sec, ..., ...)\r
return dao.getRootTaxa(sec, cdmFetch, onlyWithChildren, false);\r
}\r
\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, boolean, boolean)\r
- */\r
@Override\r
public List<Taxon> getRootTaxa(Rank rank, Reference sec, boolean onlyWithChildren,boolean withMisapplications, List<String> propertyPaths) {\r
return dao.getRootTaxa(rank, sec, null, onlyWithChildren, withMisapplications, propertyPaths);\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllRelationships(int, int)\r
- */\r
@Override\r
public List<RelationshipBase> getAllRelationships(int limit, int start){\r
return dao.getAllRelationships(limit, start);\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#changeSynonymToAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)\r
*/\r
- //TODO correct delete handling still needs to be implemented / checked\r
+\r
@Override\r
@Transactional(readOnly = false)\r
public Taxon changeSynonymToAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon, boolean deleteSynonym, boolean copyCitationInfo, Reference citation, String microCitation) throws HomotypicalGroupChangeException{\r
\r
SynonymRelationshipType relTypeForGroup = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();\r
List<Synonym> heteroSynonyms = acceptedTaxon.getSynonymsInGroup(synonymHomotypicGroup);\r
+ Set<NameRelationship> basionymsAndReplacedSynonyms = synonymHomotypicGroup.getBasionymAndReplacedSynonymRelations();\r
\r
for (Synonym heteroSynonym : heteroSynonyms){\r
if (synonym.equals(heteroSynonym)){\r
acceptedTaxon.removeSynonym(heteroSynonym, false);\r
+\r
}else{\r
//move synonyms in same homotypic group to new accepted taxon\r
heteroSynonym.replaceAcceptedTaxon(newAcceptedTaxon, relTypeForGroup, copyCitationInfo, citation, microCitation);\r
}\r
\r
//synonym.getName().removeTaxonBase(synonym);\r
- //TODO correct delete handling still needs to be implemented / checked\r
+\r
if (deleteSynonym){\r
// deleteSynonym(synonym, taxon, false);\r
try {\r
this.dao.flush();\r
- this.delete(synonym);\r
+ SynonymDeletionConfigurator config = new SynonymDeletionConfigurator();\r
+ config.setDeleteNameIfPossible(false);\r
+ this.deleteSynonym(synonym, acceptedTaxon, config);\r
\r
} catch (Exception e) {\r
logger.info("Can't delete old synonym from database");\r
// Get name from synonym\r
TaxonNameBase<?, ?> synonymName = synonym.getName();\r
\r
- // remove synonym from taxon\r
+ /* // remove synonym from taxon\r
toTaxon.removeSynonym(synonym);\r
-\r
+*/\r
// Create a taxon with synonym name\r
Taxon fromTaxon = Taxon.NewInstance(synonymName, null);\r
\r
\r
// since we are swapping names, we have to detach the name from the synonym completely.\r
// Otherwise the synonym will still be in the list of typified names.\r
- synonym.getName().removeTaxonBase(synonym);\r
+ // synonym.getName().removeTaxonBase(synonym);\r
+ this.deleteSynonym(synonym, null);\r
\r
return fromTaxon;\r
}\r
\r
\r
// Switch groups\r
- oldHomotypicalGroup.removeTypifiedName(synonymName);\r
+ oldHomotypicalGroup.removeTypifiedName(synonymName, false);\r
newHomotypicalGroup.addTypifiedName(synonymName);\r
\r
//remove existing basionym relationships\r
this.dao = dao;\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank, java.lang.Integer, java.lang.Integer)\r
- */\r
@Override\r
- public Pager<TaxonBase> findTaxaByName(Class<? extends TaxonBase> clazz,\r
- String uninomial, String infragenericEpithet, String specificEpithet,\r
- String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {\r
+ public Pager<TaxonBase> findTaxaByName(Class<? extends TaxonBase> clazz, String uninomial, String infragenericEpithet, String specificEpithet, String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {\r
Integer numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);\r
\r
List<TaxonBase> results = new ArrayList<TaxonBase>();\r
return new DefaultPagerImpl<TaxonBase>(pageNumber, numberOfResults, pageSize, results);\r
}\r
\r
-\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxaByName(java.lang.Class, java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.name.Rank, java.lang.Integer, java.lang.Integer)\r
- */\r
@Override\r
public List<TaxonBase> listTaxaByName(Class<? extends TaxonBase> clazz, String uninomial, String infragenericEpithet, String specificEpithet, String infraspecificEpithet, Rank rank, Integer pageSize,Integer pageNumber) {\r
Integer numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);\r
return results;\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#listToTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
- */\r
@Override\r
public List<TaxonRelationship> listToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);\r
return results;\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#pageToTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
- */\r
@Override\r
public Pager<TaxonRelationship> pageToTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedTo);\r
return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#listFromTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
- */\r
@Override\r
public List<TaxonRelationship> listFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);\r
return results;\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#pageFromTaxonRelationships(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
- */\r
@Override\r
public Pager<TaxonRelationship> pageFromTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countTaxonRelationships(taxon, type, TaxonRelationship.Direction.relatedFrom);\r
return new DefaultPagerImpl<TaxonRelationship>(pageNumber, numberOfResults, pageSize, results);\r
}\r
\r
- /**\r
- * @param taxon\r
- * @param includeRelationships\r
- * @param maxDepth\r
- * @param limit\r
- * @param starts\r
- * @param propertyPaths\r
- * @return an List which is not specifically ordered\r
- */\r
+ @Override\r
+ public List<Taxon> listAcceptedTaxaFor(UUID synonymUuid, UUID classificationUuid, Integer pageSize, Integer pageNumber,\r
+ List<OrderHint> orderHints, List<String> propertyPaths){\r
+ return pageAcceptedTaxaFor(synonymUuid, classificationUuid, pageSize, pageNumber, orderHints, propertyPaths).getRecords();\r
+ }\r
+\r
+ @Override\r
+ public Pager<Taxon> pageAcceptedTaxaFor(UUID synonymUuid, UUID classificationUuid, Integer pageSize, Integer pageNumber,\r
+ List<OrderHint> orderHints, List<String> propertyPaths){\r
+\r
+ List<Taxon> list = new ArrayList<Taxon>();\r
+ Long count = 0l;\r
+\r
+ Synonym synonym = null;\r
+\r
+ try {\r
+ synonym = (Synonym) dao.load(synonymUuid);\r
+ } catch (ClassCastException e){\r
+ throw new EntityNotFoundException("The TaxonBase entity referenced by " + synonymUuid + " is not a Synonmy");\r
+ } catch (NullPointerException e){\r
+ throw new EntityNotFoundException("No TaxonBase entity found for " + synonymUuid);\r
+ }\r
+\r
+ Classification classificationFilter = null;\r
+ if(classificationUuid != null){\r
+ try {\r
+ classificationFilter = classificationDao.load(classificationUuid);\r
+ } catch (NullPointerException e){\r
+ throw new EntityNotFoundException("No Classification entity found for " + classificationUuid);\r
+ }\r
+ if(classificationFilter == null){\r
+\r
+ }\r
+ }\r
+\r
+ count = dao.countAcceptedTaxaFor(synonym, classificationFilter) ;\r
+ if(count > (pageSize * pageNumber)){\r
+ list = dao.listAcceptedTaxaFor(synonym, classificationFilter, pageSize, pageNumber, orderHints, propertyPaths);\r
+ }\r
+\r
+ return new DefaultPagerImpl<Taxon>(pageNumber, count.intValue(), pageSize, list);\r
+ }\r
+\r
+\r
@Override\r
public Set<Taxon> listRelatedTaxa(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships, Integer maxDepth,\r
Integer limit, Integer start, List<String> propertyPaths) {\r
taxa.add(taxon);\r
}\r
\r
+ if(includeRelationships.isEmpty()){\r
+ return taxa;\r
+ }\r
+\r
if(maxDepth != null) {\r
maxDepth--;\r
}\r
return new DefaultPagerImpl<SynonymRelationship>(pageNumber, numberOfResults, pageSize, results);\r
}\r
\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
+ */\r
+ @Override\r
+ public List<List<Synonym>> getSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){\r
+ List<List<Synonym>> result = new ArrayList<List<Synonym>>();\r
+ Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);\r
+\r
+ //homotypic\r
+ result.add(t.getHomotypicSynonymsByHomotypicGroup());\r
+\r
+ //heterotypic\r
+ List<HomotypicalGroup> homotypicalGroups = t.getHeterotypicSynonymyGroups();\r
+ for(HomotypicalGroup homotypicalGroup : homotypicalGroups){\r
+ result.add(t.getSynonymsInGroup(homotypicalGroup));\r
+ }\r
+\r
+ return result;\r
+\r
+ }\r
+\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getHomotypicSynonymsByHomotypicGroup(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
*/\r
}\r
\r
@Override\r
- public List<UuidAndTitleCache<TaxonBase>> findTaxaAndNamesForEditor(IFindTaxaAndNamesConfigurator configurator){\r
-\r
- List<UuidAndTitleCache<TaxonBase>> result = new ArrayList<UuidAndTitleCache<TaxonBase>>();\r
-// Class<? extends TaxonBase> clazz = null;\r
-// if ((configurator.isDoTaxa() && configurator.isDoSynonyms())) {\r
-// clazz = TaxonBase.class;\r
-// //propertyPath.addAll(configurator.getTaxonPropertyPath());\r
-// //propertyPath.addAll(configurator.getSynonymPropertyPath());\r
-// } else if(configurator.isDoTaxa()) {\r
-// clazz = Taxon.class;\r
-// //propertyPath = configurator.getTaxonPropertyPath();\r
-// } else if (configurator.isDoSynonyms()) {\r
-// clazz = Synonym.class;\r
-// //propertyPath = configurator.getSynonymPropertyPath();\r
-// }\r
+ public List<UuidAndTitleCache<IdentifiableEntity>> findTaxaAndNamesForEditor(IFindTaxaAndNamesConfigurator configurator){\r
\r
+ List<UuidAndTitleCache<IdentifiableEntity>> results = new ArrayList<UuidAndTitleCache<IdentifiableEntity>>();\r
\r
- result = dao.getTaxaByNameForEditor(configurator.isDoTaxa(), configurator.isDoSynonyms(), configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());\r
- return result;\r
+\r
+ if (configurator.isDoSynonyms() || configurator.isDoTaxa() || configurator.isDoNamesWithoutTaxa()){\r
+ results = dao.getTaxaByNameForEditor(configurator.isDoTaxa(), configurator.isDoSynonyms(), configurator.isDoNamesWithoutTaxa(), configurator.isDoMisappliedNames(),configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());\r
+ }\r
+ if (configurator.isDoTaxaByCommonNames()) {\r
+ //if(configurator.getPageSize() == null ){\r
+ List<UuidAndTitleCache<IdentifiableEntity>> commonNameResults = dao.getTaxaByCommonNameForEditor(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());\r
+ if(commonNameResults != null){\r
+ results.addAll(commonNameResults);\r
+ }\r
+ // }\r
+ }\r
+ return results;\r
}\r
\r
/* (non-Javadoc)\r
numberTaxaResults = dao.countTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas());\r
}\r
if(configurator.getPageSize() == null || numberTaxaResults > configurator.getPageSize() * configurator.getPageNumber()){\r
- List<Object[]> commonNameResults = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());\r
- for( Object[] entry : commonNameResults ) {\r
- taxa.add((TaxonBase) entry[0]);\r
- }\r
+ List<Taxon> commonNameResults = dao.getTaxaByCommonName(configurator.getTitleSearchStringSqlized(), configurator.getClassification(), configurator.getMatchMode(), configurator.getNamedAreas(), configurator.getPageSize(), configurator.getPageNumber(), configurator.getTaxonPropertyPath());\r
+ taxa.addAll(commonNameResults);\r
}\r
if(taxa != null){\r
results.addAll(taxa);\r
Boolean limitToGalleries, Boolean includeTaxonDescriptions, Boolean includeOccurrences,\r
Boolean includeTaxonNameDescriptions, List<String> propertyPath) {\r
\r
+ logger.trace("listMedia() - START");\r
+\r
Set<Taxon> taxa = new HashSet<Taxon>();\r
List<Media> taxonMedia = new ArrayList<Media>();\r
+ List<Media> nonImageGalleryImages = new ArrayList<Media>();\r
\r
if (limitToGalleries == null) {\r
limitToGalleries = false;\r
}\r
\r
// --- resolve related taxa\r
- if (includeRelationships != null) {\r
+ if (includeRelationships != null && ! includeRelationships.isEmpty()) {\r
+ logger.trace("listMedia() - resolve related taxa");\r
taxa = listRelatedTaxa(taxon, includeRelationships, null, null, null, null);\r
}\r
\r
taxa.add((Taxon) dao.load(taxon.getUuid()));\r
\r
if(includeTaxonDescriptions != null && includeTaxonDescriptions){\r
+ logger.trace("listMedia() - includeTaxonDescriptions");\r
List<TaxonDescription> taxonDescriptions = new ArrayList<TaxonDescription>();\r
// --- TaxonDescriptions\r
for (Taxon t : taxa) {\r
if (!limitToGalleries || taxonDescription.isImageGallery()) {\r
for (DescriptionElementBase element : taxonDescription.getElements()) {\r
for (Media media : element.getMedia()) {\r
- taxonMedia.add(media);\r
+ if(taxonDescription.isImageGallery()){\r
+ taxonMedia.add(media);\r
+ }\r
+ else{\r
+ nonImageGalleryImages.add(media);\r
+ }\r
}\r
}\r
}\r
}\r
+ //put images from image gallery first (#3242)\r
+ taxonMedia.addAll(nonImageGalleryImages);\r
}\r
\r
+\r
if(includeOccurrences != null && includeOccurrences) {\r
+ logger.trace("listMedia() - includeOccurrences");\r
Set<SpecimenOrObservationBase> specimensOrObservations = new HashSet<SpecimenOrObservationBase>();\r
// --- Specimens\r
for (Taxon t : taxa) {\r
// Collection\r
//TODO why may collections have media attached? #\r
if (occurrence.isInstanceOf(DerivedUnit.class)) {\r
- DerivedUnit derivedUnit = CdmBase.deproxy(occurrence, DerivedUnit.class);\r
+ DerivedUnit derivedUnit = CdmBase.deproxy(occurrence, DerivedUnit.class);\r
if (derivedUnit.getCollection() != null){\r
taxonMedia.addAll(derivedUnit.getCollection().getMedia());\r
}\r
\r
// pherograms & gelPhotos\r
if (occurrence.isInstanceOf(DnaSample.class)) {\r
- DnaSample dnaSample = CdmBase.deproxy(occurrence, DnaSample.class);\r
- Set<Sequence> sequences = dnaSample.getSequences();\r
- //we do show only those gelPhotos which lead to a consensus sequence\r
- for (Sequence sequence : sequences) {\r
- Set<Media> dnaRelatedMedia = new HashSet<Media>();\r
- for (SingleRead singleRead : sequence.getSingleReads()){\r
- Amplification amplification = singleRead.getAmplification();\r
- dnaRelatedMedia.add(amplification.getGelPhoto());\r
- dnaRelatedMedia.add(singleRead.getPherogram());\r
- dnaRelatedMedia.remove(null);\r
- }\r
- taxonMedia.addAll(dnaRelatedMedia);\r
+ DnaSample dnaSample = CdmBase.deproxy(occurrence, DnaSample.class);\r
+ Set<Sequence> sequences = dnaSample.getSequences();\r
+ //we do show only those gelPhotos which lead to a consensus sequence\r
+ for (Sequence sequence : sequences) {\r
+ Set<Media> dnaRelatedMedia = new HashSet<Media>();\r
+ for (SingleRead singleRead : sequence.getSingleReads()){\r
+ AmplificationResult amplification = singleRead.getAmplificationResult();\r
+ dnaRelatedMedia.add(amplification.getGelPhoto());\r
+ dnaRelatedMedia.add(singleRead.getPherogram());\r
+ dnaRelatedMedia.remove(null);\r
+ }\r
+ taxonMedia.addAll(dnaRelatedMedia);\r
}\r
}\r
\r
}\r
\r
if(includeTaxonNameDescriptions != null && includeTaxonNameDescriptions) {\r
+ logger.trace("listMedia() - includeTaxonNameDescriptions");\r
// --- TaxonNameDescription\r
Set<TaxonNameDescription> nameDescriptions = new HashSet<TaxonNameDescription>();\r
for (Taxon t : taxa) {\r
}\r
}\r
\r
+\r
+ logger.trace("listMedia() - initialize");\r
beanInitializer.initializeAll(taxonMedia, propertyPath);\r
+\r
+ logger.trace("listMedia() - END");\r
+\r
return taxonMedia;\r
}\r
\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator)\r
*/\r
@Override\r
- public void deleteTaxon(Taxon taxon, TaxonDeletionConfigurator config) throws ReferencedObjectUndeletableException {\r
- if (config == null){\r
+ public DeleteResult deleteTaxon(Taxon taxon, TaxonDeletionConfigurator config, Classification classification) {\r
+\r
+ if (config == null){\r
config = new TaxonDeletionConfigurator();\r
}\r
\r
- // TaxonNode\r
- if (! config.isDeleteTaxonNodes()){\r
- if (taxon.getTaxonNodes().size() > 0){\r
- String message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion.";\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
- }\r
-\r
+ DeleteResult result = isDeletable(taxon, config);\r
\r
- // SynonymRelationShip\r
+ if (result.isOk()){\r
+ // --- DeleteSynonymRelations\r
if (config.isDeleteSynonymRelations()){\r
boolean removeSynonymNameFromHomotypicalGroup = false;\r
- for (SynonymRelationship synRel : taxon.getSynonymRelations()){\r
+ // use tmp Set to avoid concurrent modification\r
+ Set<SynonymRelationship> synRelsToDelete = new HashSet<SynonymRelationship>();\r
+ synRelsToDelete.addAll(taxon.getSynonymRelations());\r
+ for (SynonymRelationship synRel : synRelsToDelete){\r
Synonym synonym = synRel.getSynonym();\r
+ // taxon.removeSynonymRelation will set the accepted taxon and the synonym to NULL\r
+ // this will cause hibernate to delete the relationship since\r
+ // the SynonymRelationship field on both is annotated with removeOrphan\r
+ // so no further explicit deleting of the relationship should be done here\r
taxon.removeSynonymRelation(synRel, removeSynonymNameFromHomotypicalGroup);\r
+\r
+ // --- DeleteSynonymsIfPossible\r
if (config.isDeleteSynonymsIfPossible()){\r
//TODO which value\r
boolean newHomotypicGroupIfNeeded = true;\r
- deleteSynonym(synonym, taxon, config.isDeleteNameIfPossible(), newHomotypicGroupIfNeeded);\r
- }else{\r
- deleteSynonymRelationships(synonym, taxon);\r
+ SynonymDeletionConfigurator synConfig = new SynonymDeletionConfigurator();\r
+ deleteSynonym(synonym, taxon, synConfig);\r
}\r
+ // relationship will be deleted by hibernate automatically,\r
+ // see comment above and http://dev.e-taxonomy.eu/trac/ticket/3797\r
+ // else{\r
+ // deleteSynonymRelationships(synonym, taxon);\r
+ // }\r
}\r
}\r
\r
- // TaxonRelationship\r
+ // --- DeleteTaxonRelationships\r
if (! config.isDeleteTaxonRelationships()){\r
if (taxon.getTaxonRelations().size() > 0){\r
- String message = "Taxon can't be deleted as it is related to another taxon. Remove taxon from all relations to other taxa prior to deletion.";\r
- throw new ReferencedObjectUndeletableException(message);\r
+ String message = "Taxon can't be deleted as it is related to another taxon. " +\r
+ "Remove taxon from all relations to other taxa prior to deletion.";\r
+ // throw new ReferencedObjectUndeletableException(message);\r
}\r
- }\r
+ } else{\r
+ for (TaxonRelationship taxRel: taxon.getTaxonRelations()){\r
+ if (config.isDeleteMisappliedNamesAndInvalidDesignations()){\r
+ if (taxRel.getType().equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR()) || taxRel.getType().equals(TaxonRelationshipType.INVALID_DESIGNATION_FOR())){\r
+ if (taxon.equals(taxRel.getToTaxon())){\r
+ this.deleteTaxon(taxRel.getFromTaxon(), config, classification);\r
+ }\r
+ }\r
+ }\r
+ taxon.removeTaxonRelation(taxRel);\r
+ /*if (taxFrom.equals(taxon)){\r
+ try{\r
+ this.deleteTaxon(taxTo, taxConf, classification);\r
+ } catch(DataChangeNoRollbackException e){\r
+ logger.debug("A related taxon will not be deleted." + e.getMessage());\r
+ }\r
+ } else {\r
+ try{\r
+ this.deleteTaxon(taxFrom, taxConf, classification);\r
+ } catch(DataChangeNoRollbackException e){\r
+ logger.debug("A related taxon will not be deleted." + e.getMessage());\r
+ }\r
\r
+ }*/\r
+ }\r
+ }\r
\r
// TaxonDescription\r
- Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
-\r
- for (TaxonDescription desc: descriptions){\r
- if (config.isDeleteDescriptions()){\r
- //TODO use description delete configurator ?\r
- //FIXME check if description is ALWAYS deletable\r
- descriptionService.delete(desc);\r
- }else{\r
- if (desc.getDescribedSpecimenOrObservation() != null){\r
- String message = "Taxon can't be deleted as it is used in a TaxonDescription" +\r
- " which also describes specimens or abservations";\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
+ if (config.isDeleteDescriptions()){\r
+ Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
+ List<TaxonDescription> removeDescriptions = new ArrayList<TaxonDescription>();\r
+ for (TaxonDescription desc: descriptions){\r
+ //TODO use description delete configurator ?\r
+ //FIXME check if description is ALWAYS deletable\r
+ if (desc.getDescribedSpecimenOrObservation() != null){\r
+ String message = "Taxon can't be deleted as it is used in a TaxonDescription" +\r
+ " which also describes specimens or abservations";\r
+ //throw new ReferencedObjectUndeletableException(message);\r
+ }\r
+ removeDescriptions.add(desc);\r
+ descriptionService.delete(desc);\r
+\r
+ }\r
+ for (TaxonDescription desc: removeDescriptions){\r
+ taxon.removeDescription(desc);\r
+ }\r
+ }\r
+\r
+\r
+ /* //check references with only reverse mapping\r
+ String message = checkForReferences(taxon);\r
+ if (message != null){\r
+ //throw new ReferencedObjectUndeletableException(message.toString());\r
+ }*/\r
+\r
+ if (! config.isDeleteTaxonNodes() || (!config.isDeleteInAllClassifications() && classification == null )){\r
+ //if (taxon.getTaxonNodes().size() > 0){\r
+ // message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion or define a classification where it should be deleted or adapt the taxon deletion configurator.";\r
+ // throw new ReferencedObjectUndeletableException(message);\r
+ //}\r
+ }else{\r
+ if (taxon.getTaxonNodes().size() != 0){\r
+ Set<TaxonNode> nodes = taxon.getTaxonNodes();\r
+ Iterator<TaxonNode> iterator = nodes.iterator();\r
+ TaxonNode node = null;\r
+ boolean deleteChildren;\r
+ if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)){\r
+ deleteChildren = true;\r
+ }else {\r
+ deleteChildren = false;\r
+ }\r
+ boolean success = true;\r
+ if (!config.isDeleteInAllClassifications() && !(classification == null)){\r
+ while (iterator.hasNext()){\r
+ node = iterator.next();\r
+ if (node.getClassification().equals(classification)){\r
+ break;\r
}\r
+ node = null;\r
}\r
+ if (node != null){\r
+ success =taxon.removeTaxonNode(node, deleteChildren);\r
+ nodeService.delete(node);\r
+ } else {\r
+ result.setError();\r
+ result.addException(new Exception("The taxon can not be deleted because it is not used in defined classification."));\r
+ }\r
+ } else if (config.isDeleteInAllClassifications()){\r
+ Set<ITaxonTreeNode> nodesList = new HashSet<ITaxonTreeNode>();\r
+ nodesList.addAll(taxon.getTaxonNodes());\r
+\r
+ for (ITaxonTreeNode treeNode: nodesList){\r
+ TaxonNode taxonNode = (TaxonNode) treeNode;\r
+ if(!deleteChildren){\r
+ /* Object[] childNodes = taxonNode.getChildNodes().toArray();\r
+ //nodesList.addAll(taxonNode.getChildNodes());\r
+ for (Object childNode: childNodes){\r
+ TaxonNode childNodeCast = (TaxonNode) childNode;\r
+ deleteTaxon(childNodeCast.getTaxon(), config, classification);\r
\r
+ }\r
\r
- //check references with only reverse mapping\r
- Set<CdmBase> referencingObjects = genericDao.getReferencingObjects(taxon);\r
- for (CdmBase referencingObject : referencingObjects){\r
- //IIdentificationKeys (Media, Polytomous, MultiAccess)\r
- if (HibernateProxyHelper.isInstanceOf(referencingObject, IIdentificationKey.class)){\r
- String message = "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";\r
- message = String.format(message, CdmBase.deproxy(referencingObject, DerivedUnit.class).getTitleCache());\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
-\r
+ /*for (TaxonNode childNode: taxonNode.getChildNodes()){\r
+ deleteTaxon(childNode.getTaxon(), config, classification);\r
\r
- //PolytomousKeyNode\r
- if (referencingObject.isInstanceOf(PolytomousKeyNode.class)){\r
- String message = "Taxon can't be deleted as it is used in polytomous key node";\r
- throw new ReferencedObjectUndeletableException(message);\r
- }\r
+ }\r
+ // taxon.removeTaxonNode(taxonNode);\r
+ //nodeService.delete(taxonNode);\r
+ } else{\r
+ */\r
+ Object[] childNodes = taxonNode.getChildNodes().toArray();\r
+ for (Object childNode: childNodes){\r
+ TaxonNode childNodeCast = (TaxonNode) childNode;\r
+ taxonNode.getParent().addChildNode(childNodeCast, childNodeCast.getReference(), childNodeCast.getMicroReference());\r
+ }\r
\r
- //TaxonInteraction\r
- if (referencingObject.isInstanceOf(TaxonInteraction.class)){\r
- String message = "Taxon can't be deleted as it is used in taxonInteraction#taxon2";\r
- throw new ReferencedObjectUndeletableException(message);\r
+ //taxon.removeTaxonNode(taxonNode);\r
+ }\r
+ }\r
+ config.getTaxonNodeConfig().setDeleteTaxon(false);\r
+ DeleteResult resultNodes = nodeService.deleteTaxonNodes(nodesList, config);\r
+ if (!resultNodes.isOk()){\r
+ result.addExceptions(resultNodes.getExceptions());\r
+ result.setStatus(resultNodes.getStatus());\r
+ }\r
+ }\r
+ if (!success){\r
+ result.setError();\r
+ result.addException(new Exception("The taxon can not be deleted because the taxon node can not be removed."));\r
+ }\r
}\r
}\r
\r
\r
+ //PolytomousKey TODO\r
+\r
+\r
//TaxonNameBase\r
if (config.isDeleteNameIfPossible()){\r
- try {\r
- nameService.delete(taxon.getName(), config.getNameDeletionConfig());\r
- } catch (ReferencedObjectUndeletableException e) {\r
- //do nothing\r
- if (logger.isDebugEnabled()){logger.debug("Name could not be deleted");}\r
- }\r
+\r
+\r
+ //TaxonNameBase name = nameService.find(taxon.getName().getUuid());\r
+ TaxonNameBase name = (TaxonNameBase)HibernateProxyHelper.deproxy(taxon.getName());\r
+ //check whether taxon will be deleted or not\r
+ if ((taxon.getTaxonNodes() == null || taxon.getTaxonNodes().size()== 0) && name != null ){\r
+ taxon = (Taxon) HibernateProxyHelper.deproxy(taxon);\r
+ //name.removeTaxonBase(taxon);\r
+ //nameService.saveOrUpdate(name);\r
+ taxon.setName(null);\r
+ //dao.delete(taxon);\r
+ DeleteResult nameResult = new DeleteResult();\r
+\r
+ //remove name if possible (and required)\r
+ if (name != null && config.isDeleteNameIfPossible()){\r
+ nameResult = nameService.delete(name, config.getNameDeletionConfig());\r
+ }\r
+ \r
+ if (nameResult.isError()){\r
+ //result.setError();\r
+ result.addRelatedObject(name);\r
+ result.addExceptions(nameResult.getExceptions());\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+// TaxonDescription\r
+ /* Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
+\r
+ for (TaxonDescription desc: descriptions){\r
+ if (config.isDeleteDescriptions()){\r
+ //TODO use description delete configurator ?\r
+ //FIXME check if description is ALWAYS deletable\r
+ taxon.removeDescription(desc);\r
+ descriptionService.delete(desc);\r
+ }else{\r
+ if (desc.getDescribedSpecimenOrObservations().size()>0){\r
+ String message = "Taxon can't be deleted as it is used in a TaxonDescription" +\r
+ " which also describes specimens or observations";\r
+ throw new ReferencedObjectUndeletableException(message);\r
+ }\r
+ }\r
+ }*/\r
+\r
+ if ((taxon.getTaxonNodes() == null || taxon.getTaxonNodes().size()== 0) ){\r
+ try{\r
+ UUID uuid = dao.delete(taxon);\r
+\r
+ }catch(Exception e){\r
+ result.addException(e);\r
+ result.setError();\r
+\r
+ }\r
+ } else {\r
+ result.setError();\r
+ result.addException(new Exception("The Taxon can't be deleted."));\r
+\r
}\r
+ }\r
+// }else {\r
+// List<Exception> exceptions = new ArrayList<Exception>();\r
+// for (String message: referencedObjects){\r
+// ReferencedObjectUndeletableException exception = new ReferencedObjectUndeletableException(message);\r
+// exceptions.add(exception);\r
+// }\r
+// result.addExceptions(exceptions);\r
+// result.setError();\r
+//\r
+// }\r
+ return result;\r
\r
}\r
\r
+ private String checkForReferences(Taxon taxon){\r
+ Set<CdmBase> referencingObjects = genericDao.getReferencingObjects(taxon);\r
+ for (CdmBase referencingObject : referencingObjects){\r
+ //IIdentificationKeys (Media, Polytomous, MultiAccess)\r
+ if (HibernateProxyHelper.isInstanceOf(referencingObject, IIdentificationKey.class)){\r
+ String message = "Taxon" + taxon.getTitleCache() + "can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";\r
+\r
+ return message;\r
+ }\r
+\r
+\r
+ /* //PolytomousKeyNode\r
+ if (referencingObject.isInstanceOf(PolytomousKeyNode.class)){\r
+ String message = "Taxon" + taxon.getTitleCache() + " can't be deleted as it is used in polytomous key node";\r
+ return message;\r
+ }*/\r
+\r
+ //TaxonInteraction\r
+ if (referencingObject.isInstanceOf(TaxonInteraction.class)){\r
+ String message = "Taxon can't be deleted as it is used in taxonInteraction#taxon2";\r
+ return message;\r
+ }\r
+\r
+ //TaxonInteraction\r
+ if (referencingObject.isInstanceOf(DeterminationEvent.class)){\r
+ String message = "Taxon can't be deleted as it is used in a determination event";\r
+ return message;\r
+ }\r
+\r
+ }\r
+\r
+ referencingObjects = null;\r
+ return null;\r
+ }\r
+\r
+ private boolean checkForPolytomousKeys(Taxon taxon){\r
+ boolean result = false;\r
+ List<CdmBase> list = genericDao.getCdmBasesByFieldAndClass(PolytomousKeyNode.class, "taxon", taxon);\r
+ if (!list.isEmpty()) {\r
+ result = true;\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @Transactional(readOnly = false)\r
+ public UUID delete(Synonym syn){\r
+ UUID result = syn.getUuid();\r
+ this.deleteSynonym(syn, null);\r
+ return result;\r
+ }\r
+\r
+\r
+\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)\r
*/\r
@Transactional(readOnly = false)\r
@Override\r
- public void deleteSynonym(Synonym synonym, Taxon taxon, boolean removeNameIfPossible,boolean newHomotypicGroupIfNeeded) {\r
- if (synonym == null){\r
- return;\r
- }\r
- synonym = CdmBase.deproxy(dao.merge(synonym), Synonym.class);\r
+ public DeleteResult deleteSynonym(Synonym synonym, SynonymDeletionConfigurator config) {\r
+ return deleteSynonym(synonym, null, config);\r
\r
- //remove synonymRelationship\r
- Set<Taxon> taxonSet = new HashSet<Taxon>();\r
- if (taxon != null){\r
- taxonSet.add(taxon);\r
- }else{\r
- taxonSet.addAll(synonym.getAcceptedTaxa());\r
+ }\r
+\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonym(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon, boolean, boolean)\r
+ */\r
+ @Transactional(readOnly = false)\r
+ @Override\r
+ public DeleteResult deleteSynonym(Synonym synonym, Taxon taxon, SynonymDeletionConfigurator config) {\r
+ DeleteResult result = new DeleteResult();\r
+ if (synonym == null){\r
+ result.setAbort();\r
+ return result;\r
}\r
- for (Taxon relatedTaxon : taxonSet){\r
-// dao.deleteSynonymRelationships(synonym, relatedTaxon);\r
- relatedTaxon.removeSynonym(synonym, newHomotypicGroupIfNeeded);\r
+\r
+ if (config == null){\r
+ config = new SynonymDeletionConfigurator();\r
}\r
- this.saveOrUpdate(synonym);\r
+ result = isDeletable(synonym, config);\r
\r
- //TODO remove name from homotypical group?\r
\r
- //remove synonym (if necessary)\r
- if (synonym.getSynonymRelations().isEmpty()){\r
- TaxonNameBase<?,?> name = synonym.getName();\r
- synonym.setName(null);\r
- dao.delete(synonym);\r
+ if (result.isOk()){\r
+ synonym = CdmBase.deproxy(dao.merge(synonym), Synonym.class);\r
+\r
+ //remove synonymRelationship\r
+ Set<Taxon> taxonSet = new HashSet<Taxon>();\r
+ if (taxon != null){\r
+ taxonSet.add(taxon);\r
+ }else{\r
+ taxonSet.addAll(synonym.getAcceptedTaxa());\r
+ }\r
+ for (Taxon relatedTaxon : taxonSet){\r
+ relatedTaxon = HibernateProxyHelper.deproxy(relatedTaxon, Taxon.class);\r
+ relatedTaxon.removeSynonym(synonym, false);\r
+ this.saveOrUpdate(relatedTaxon);\r
+ }\r
+ this.saveOrUpdate(synonym);\r
+\r
+ //TODO remove name from homotypical group?\r
+\r
+ //remove synonym (if necessary)\r
+\r
+ if (synonym.getSynonymRelations().isEmpty()){\r
+ TaxonNameBase<?,?> name = synonym.getName();\r
+ synonym.setName(null);\r
+ dao.delete(synonym);\r
+\r
+ //remove name if possible (and required)\r
+ if (name != null && config.isDeleteNameIfPossible()){\r
+\r
+ DeleteResult nameDeleteresult = nameService.delete(name, config.getNameDeletionConfig());\r
+ if (nameDeleteresult.isAbort()){\r
+ result.addExceptions(nameDeleteresult.getExceptions());\r
+ result.addUpdatedObject(name);\r
+ }\r
\r
- //remove name if possible (and required)\r
- if (name != null && removeNameIfPossible){\r
- try{\r
- nameService.delete(name, new NameDeletionConfigurator());\r
- }catch (DataChangeNoRollbackException ex){\r
- if (logger.isDebugEnabled()) {\r
- logger.debug("Name wasn't deleted as it is referenced");\r
- }\r
}\r
+\r
+ }else {\r
+ result.setError();\r
+ result.addException(new ReferencedObjectUndeletableException("Synonym can not be deleted it is used in a synonymRelationship."));\r
+ return result;\r
}\r
+\r
+\r
}\r
+ return result;\r
+// else{\r
+// List<Exception> exceptions = new ArrayList<Exception>();\r
+// for (String message :messages){\r
+// exceptions.add(new ReferencedObjectUndeletableException(message));\r
+// }\r
+// result.setError();\r
+// result.addExceptions(exceptions);\r
+// return result;\r
+// }\r
+\r
+\r
}\r
\r
\r
if (newRefDetail == null && keepReference){\r
newRefDetail = synRelation.getCitationMicroReference();\r
}\r
+ newTaxon = HibernateProxyHelper.deproxy(newTaxon, Taxon.class);\r
+ fromTaxon = HibernateProxyHelper.deproxy(fromTaxon, Taxon.class);\r
SynonymRelationship newSynRelation = newTaxon.addSynonym(syn, newSynonymRelationshipType, newReference, newRefDetail);\r
fromTaxon.removeSynonymRelation(synRelation, false);\r
//\r
}\r
\r
}\r
+ saveOrUpdate(fromTaxon);\r
saveOrUpdate(newTaxon);\r
//Assert that there is a result\r
if (result == null){\r
boolean highlightFragments, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
\r
\r
- LuceneSearch luceneSearch = prepareFindByFullTextSearch(clazz, queryString, classification, languages, highlightFragments);\r
+ LuceneSearch luceneSearch = prepareFindByFullTextSearch(clazz, queryString, classification, languages, highlightFragments, null);\r
\r
// --- execute search\r
TopGroupsWithMaxScore topDocsResultSet = luceneSearch.executeSearch(pageSize, pageNumber);\r
}\r
\r
@Override\r
- public Pager<SearchResult<TaxonBase>> findByDistribution(List<NamedArea> areaFilter, List<PresenceAbsenceTermBase<?>> statusFilter,\r
+ public Pager<SearchResult<TaxonBase>> findByDistribution(List<NamedArea> areaFilter, List<PresenceAbsenceTerm> statusFilter,\r
Classification classification,\r
Integer pageSize, Integer pageNumber,\r
List<OrderHint> orderHints, List<String> propertyPaths) throws IOException, ParseException {\r
* @param classification\r
* @param languages\r
* @param highlightFragments\r
+ * @param sortFields TODO\r
* @param directorySelectClass\r
* @return\r
*/\r
protected LuceneSearch prepareFindByFullTextSearch(Class<? extends CdmBase> clazz, String queryString, Classification classification, List<Language> languages,\r
- boolean highlightFragments) {\r
+ boolean highlightFragments, SortField[] sortFields) {\r
BooleanQuery finalQuery = new BooleanQuery();\r
BooleanQuery textQuery = new BooleanQuery();\r
\r
LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, TaxonBase.class);\r
QueryFactory taxonBaseQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(TaxonBase.class);\r
\r
- SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};\r
+ if(sortFields == null){\r
+ sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};\r
+ }\r
luceneSearch.setSortFields(sortFields);\r
\r
// ---- search criteria\r
* <li>direct, everted: {@link Direction.relatedTo}: TaxonRelationShip.relatedTo.id --> Taxon.id </li>\r
* <li>inverse: {@link Direction.relatedFrom}: TaxonRelationShip.relatedFrom.id --> Taxon.id </li>\r
* <ul>\r
- *\r
* @param queryString\r
* @param classification\r
* @param languages\r
* @param highlightFragments\r
+ * @param sortFields TODO\r
+ *\r
* @return\r
* @throws IOException\r
*/\r
protected LuceneSearch prepareFindByTaxonRelationFullTextSearch(TaxonRelationshipEdge edge, String queryString, Classification classification, List<Language> languages,\r
- boolean highlightFragments) throws IOException {\r
+ boolean highlightFragments, SortField[] sortFields) throws IOException {\r
\r
String fromField;\r
String queryTermField;\r
\r
BooleanQuery finalQuery = new BooleanQuery();\r
\r
- LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, TaxonBase.class);\r
+ LuceneSearch luceneSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, TaxonBase.class);\r
QueryFactory taxonBaseQueryFactory = luceneIndexToolProvider.newQueryFactoryFor(TaxonBase.class);\r
\r
BooleanQuery joinFromQuery = new BooleanQuery();\r
joinFromQuery.add(taxonBaseQueryFactory.newEntityIdQuery("type.id", edge.getTaxonRelationshipType()), Occur.MUST);\r
Query joinQuery = taxonBaseQueryFactory.newJoinQuery(fromField, toField, joinFromQuery, TaxonRelationship.class);\r
\r
- SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};\r
+ if(sortFields == null){\r
+ sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", SortField.STRING, false)};\r
+ }\r
luceneSearch.setSortFields(sortFields);\r
\r
finalQuery.add(joinQuery, Occur.MUST);\r
@Override\r
public Pager<SearchResult<TaxonBase>> findTaxaAndNamesByFullText(\r
EnumSet<TaxaAndNamesSearchMode> searchModes, String queryString, Classification classification,\r
- Set<NamedArea> namedAreas, Set<PresenceAbsenceTermBase<?>> distributionStatus, List<Language> languages,\r
+ Set<NamedArea> namedAreas, Set<PresenceAbsenceTerm> distributionStatus, List<Language> languages,\r
boolean highlightFragments, Integer pageSize,\r
Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)\r
throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {\r
\r
+ // FIXME: allow taxonomic ordering\r
+ // hql equivalent: order by t.name.genusOrUninomial, case when t.name.specificEpithet like '\"%\"' then 1 else 0 end, t.name.specificEpithet, t.name.rank desc, t.name.nameCache";\r
+ // this require building a special sort column by a special classBridge\r
if(highlightFragments){\r
logger.warn("findTaxaAndNamesByFullText() : fragment highlighting is " +\r
"currently not fully supported by this method and thus " +\r
\r
// convert sets to lists\r
List<NamedArea> namedAreaList = null;\r
- List<PresenceAbsenceTermBase<?>>distributionStatusList = null;\r
+ List<PresenceAbsenceTerm>distributionStatusList = null;\r
if(namedAreas != null){\r
namedAreaList = new ArrayList<NamedArea>(namedAreas.size());\r
namedAreaList.addAll(namedAreas);\r
}\r
if(distributionStatus != null){\r
- distributionStatusList = new ArrayList<PresenceAbsenceTermBase<?>>(distributionStatus.size());\r
+ distributionStatusList = new ArrayList<PresenceAbsenceTerm>(distributionStatus.size());\r
distributionStatusList.addAll(distributionStatus);\r
}\r
\r
searchModes = EnumSet.of(TaxaAndNamesSearchMode.doTaxa);\r
}\r
\r
+ // set sort order and thus override any sort orders which may have been\r
+ // defindes by prepare*Search methods\r
+ if(orderHints == null){\r
+ orderHints = OrderHint.NOMENCLATURAL_SORT_ORDER;\r
+ }\r
+ SortField[] sortFields = new SortField[orderHints.size()];\r
+ int i = 0;\r
+ for(OrderHint oh : orderHints){\r
+ sortFields[i++] = oh.toSortField();\r
+ }\r
+// SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("id", SortField.STRING, false)};\r
+// SortField[] sortFields = new SortField[]{new SortField(NomenclaturalSortOrderBrigde.NAME_SORT_FIELD_NAME, SortField.STRING, false)};\r
+\r
+\r
boolean addDistributionFilter = namedAreas != null && namedAreas.size() > 0;\r
\r
List<LuceneSearch> luceneSearches = new ArrayList<LuceneSearch>();\r
} else if (!searchModes.contains(TaxaAndNamesSearchMode.doTaxa) && searchModes.contains(TaxaAndNamesSearchMode.doSynonyms)) {\r
taxonBaseSubclass = Synonym.class;\r
}\r
- luceneSearches.add(prepareFindByFullTextSearch(taxonBaseSubclass, queryString, classification, languages, highlightFragments));\r
+ luceneSearches.add(prepareFindByFullTextSearch(taxonBaseSubclass, queryString, classification, languages, highlightFragments, sortFields));\r
idFieldMap.put(CdmBaseType.TAXON, "id");\r
/* A) does not work!!!!\r
if(addDistributionFilter){\r
Query byCommonNameJoinQuery = descriptionElementQueryFactory.newJoinQuery(\r
"inDescription.taxon.id",\r
"id",\r
- createByDescriptionElementFullTextQuery(queryString, classification, null, languages, descriptionElementQueryFactory),\r
+ QueryFactory.addTypeRestriction(\r
+ createByDescriptionElementFullTextQuery(queryString, classification, null, languages, descriptionElementQueryFactory)\r
+ , CommonTaxonName.class\r
+ ),\r
CommonTaxonName.class);\r
logger.debug("byCommonNameJoinQuery: " + byCommonNameJoinQuery.toString());\r
LuceneSearch byCommonNameSearch = new LuceneSearch(luceneIndexToolProvider, GroupByTaxonClassBridge.GROUPBY_TAXON_FIELD, Taxon.class);\r
byCommonNameSearch.setCdmTypRestriction(Taxon.class);\r
byCommonNameSearch.setQuery(byCommonNameJoinQuery);\r
+ byCommonNameSearch.setSortFields(sortFields);\r
idFieldMap.put(CdmBaseType.TAXON, "id");\r
\r
luceneSearches.add(byCommonNameSearch);\r
//\r
luceneSearches.add(prepareFindByTaxonRelationFullTextSearch(\r
new TaxonRelationshipEdge(TaxonRelationshipType.MISAPPLIED_NAME_FOR(), Direction.relatedTo),\r
- queryString, classification, languages, highlightFragments));\r
+ queryString, classification, languages, highlightFragments, sortFields));\r
idFieldMap.put(CdmBaseType.TAXON, "id");\r
\r
if(addDistributionFilter){\r
\r
// debug code for bug described above\r
DocIdSet filterMatchSet = filter.getDocIdSet(luceneIndexToolProvider.getIndexReaderFor(Taxon.class));\r
- System.err.println(DocIdBitSetPrinter.docsAsString(filterMatchSet, 100));\r
+// System.err.println(DocIdBitSetPrinter.docsAsString(filterMatchSet, 100));\r
\r
multiIndexByAreaFilter.add(filter, Occur.SHOULD);\r
}\r
if (addDistributionFilter){\r
multiSearch.setFilter(multiIndexByAreaFilter);\r
}\r
+\r
+\r
// --- execute search\r
TopGroupsWithMaxScore topDocsResultSet = multiSearch.executeSearch(pageSize, pageNumber);\r
\r
*/\r
protected Query createByDistributionJoinQuery(\r
List<NamedArea> namedAreaList,\r
- List<PresenceAbsenceTermBase<?>> distributionStatusList,\r
+ List<PresenceAbsenceTerm> distributionStatusList,\r
QueryFactory queryFactory\r
) throws IOException {\r
\r
* @return\r
*/\r
private BooleanQuery createByDistributionQuery(List<NamedArea> namedAreaList,\r
- List<PresenceAbsenceTermBase<?>> distributionStatusList, QueryFactory queryFactory) {\r
+ List<PresenceAbsenceTerm> distributionStatusList, QueryFactory queryFactory) {\r
BooleanQuery areaQuery = new BooleanQuery();\r
// area field from Distribution\r
areaQuery.add(queryFactory.newEntityIdsQuery("area.id", namedAreaList), Occur.MUST);\r
* @throws IOException\r
*/\r
protected LuceneSearch prepareByDistributionSearch(\r
- List<NamedArea> namedAreaList, List<PresenceAbsenceTermBase<?>> distributionStatusList,\r
+ List<NamedArea> namedAreaList, List<PresenceAbsenceTerm> distributionStatusList,\r
Classification classification) throws IOException {\r
\r
BooleanQuery finalQuery = new BooleanQuery();\r
Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {\r
\r
LuceneSearch luceneSearchByDescriptionElement = prepareByDescriptionElementFullTextSearch(null, queryString, classification, null, languages, highlightFragments);\r
- LuceneSearch luceneSearchByTaxonBase = prepareFindByFullTextSearch(null, queryString, classification, languages, highlightFragments);\r
+ LuceneSearch luceneSearchByTaxonBase = prepareFindByFullTextSearch(null, queryString, classification, languages, highlightFragments, null);\r
\r
LuceneMultiSearch multiSearch = new LuceneMultiSearch(luceneIndexToolProvider, luceneSearchByDescriptionElement, luceneSearchByTaxonBase);\r
\r
}\r
String genusOfTaxon = taxonName.getGenusOrUninomial();\r
Set<TaxonNode> nodes = taxon.getTaxonNodes();\r
- List<String> taxonNames = new ArrayList<String>();\r
+ List<String> taxonNames = new ArrayList<String>();\r
\r
for (TaxonNode node: nodes){\r
// HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName\r
potentialCombination.addSource(originalSource);\r
}\r
\r
- inferredSynName.generateTitle();\r
-\r
return potentialCombination;\r
}\r
\r
\r
// Add the original source\r
if (idInSourceSyn != null && idInSourceTaxon != null) {\r
- IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, \r
- idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
inferredGenus.addSource(originalSource);\r
\r
- originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, \r
- idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
inferredSynName.addSource(originalSource);\r
originalSource = null;\r
\r
}else{\r
logger.error("There is an idInSource missing: " + idInSourceSyn + " of Synonym or " + idInSourceTaxon + " of Taxon");\r
- IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, \r
- idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
inferredGenus.addSource(originalSource);\r
\r
- originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, \r
- idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
+ originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ idInSourceSyn + "; " + idInSourceTaxon, INFERRED_GENUS_NAMESPACE, sourceReference, null);\r
inferredSynName.addSource(originalSource);\r
originalSource = null;\r
}\r
\r
taxon.addSynonym(inferredGenus, SynonymRelationshipType.INFERRED_GENUS_OF());\r
\r
- inferredSynName.generateTitle();\r
-\r
-\r
return inferredGenus;\r
}\r
\r
Reference<?> sourceReference = syn.getSec();\r
\r
if (sourceReference == null){\r
- logger.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon.getSec());\r
- sourceReference = taxon.getSec();\r
+ logger.warn("The synonym has no sec reference because it is a misapplied name! Take the sec reference of taxon" + taxon.getSec());\r
+ sourceReference = taxon.getSec();\r
}\r
\r
synName = syn.getName();\r
String taxonId = idInSourceTaxon+ "; " + idInSourceSyn;\r
\r
\r
- IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, \r
- taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
+ IdentifiableSource originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
\r
inferredEpithet.addSource(originalSource);\r
\r
- originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation, \r
- taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
+ originalSource = IdentifiableSource.NewInstance(OriginalSourceType.Transformation,\r
+ taxonId, INFERRED_EPITHET_NAMESPACE, sourceReference, null);\r
\r
inferredSynName.addSource(originalSource);\r
\r
\r
taxon.addSynonym(inferredEpithet, SynonymRelationshipType.INFERRED_EPITHET_OF());\r
\r
- inferredSynName.generateTitle();\r
return inferredEpithet;\r
}\r
\r
return inferredSynonyms;\r
}\r
\r
- /* (non-Javadoc)\r
- * @see eu.etaxonomy.cdm.api.service.ITaxonService#listClassifications(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Integer, java.lang.Integer, java.util.List)\r
- */\r
@Override\r
public List<Classification> listClassifications(TaxonBase taxonBase, Integer limit, Integer start, List<String> propertyPaths) {\r
\r
return list;\r
}\r
\r
+ @Override\r
+ public Synonym changeRelatedTaxonToSynonym(Taxon fromTaxon, Taxon toTaxon, TaxonRelationshipType oldRelationshipType,\r
+ SynonymRelationshipType synonymRelationshipType) throws DataChangeNoRollbackException {\r
+ // Create new synonym using concept name\r
+ TaxonNameBase<?, ?> synonymName = fromTaxon.getName();\r
+ Synonym synonym = Synonym.NewInstance(synonymName, fromTaxon.getSec());\r
+\r
+ // Remove concept relation from taxon\r
+ toTaxon.removeTaxon(fromTaxon, oldRelationshipType);\r
+\r
+\r
+\r
+\r
+ // Create a new synonym for the taxon\r
+ SynonymRelationship synonymRelationship;\r
+ if (synonymRelationshipType != null\r
+ && synonymRelationshipType.equals(SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF())){\r
+ synonymRelationship = toTaxon.addHomotypicSynonym(synonym, null, null);\r
+ } else{\r
+ synonymRelationship = toTaxon.addHeterotypicSynonymName(synonymName);\r
+ }\r
+\r
+ this.saveOrUpdate(toTaxon);\r
+ //TODO: configurator and classification\r
+ TaxonDeletionConfigurator config = new TaxonDeletionConfigurator();\r
+ config.setDeleteNameIfPossible(false);\r
+ this.deleteTaxon(fromTaxon, config, null);\r
+ return synonymRelationship.getSynonym();\r
+\r
+ }\r
+ @Override\r
+ public DeleteResult isDeletable(TaxonBase taxonBase, DeleteConfiguratorBase config){\r
+ DeleteResult result = new DeleteResult();\r
+ Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(taxonBase);\r
+ if (taxonBase instanceof Taxon){\r
+ TaxonDeletionConfigurator taxonConfig = (TaxonDeletionConfigurator) config;\r
+ result = isDeletableForTaxon(references, taxonConfig);\r
+ }else{\r
+ SynonymDeletionConfigurator synonymConfig = (SynonymDeletionConfigurator) config;\r
+ result = isDeletableForSynonym(references, synonymConfig);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ private DeleteResult isDeletableForSynonym(Set<CdmBase> references, SynonymDeletionConfigurator config){\r
+ String message;\r
+ DeleteResult result = new DeleteResult();\r
+ for (CdmBase ref: references){\r
+ if (!(ref instanceof SynonymRelationship || ref instanceof Taxon || ref instanceof TaxonNameBase )){\r
+ message = "The Synonym can't be deleted as long as it is referenced by " + ref.getClass().getSimpleName() + " with id "+ ref.getId();\r
+ result.addException(new ReferencedObjectUndeletableException(message));\r
+ result.addRelatedObject(ref);\r
+ result.setAbort();\r
+ }\r
+ }\r
\r
+ return result;\r
+ }\r
+ private DeleteResult isDeletableForTaxon(Set<CdmBase> references, TaxonDeletionConfigurator config){\r
+ String message = null;\r
+ DeleteResult result = new DeleteResult();\r
+ for (CdmBase ref: references){\r
+ if (!(ref instanceof TaxonNameBase)){\r
+ if (!config.isDeleteSynonymRelations() && (ref instanceof SynonymRelationship)){\r
+ message = "The Taxon can't be deleted as long as it has synonyms.";\r
\r
+ }\r
+ if (!config.isDeleteDescriptions() && (ref instanceof DescriptionBase)){\r
+ message = "The Taxon can't be deleted as long as it has factual data.";\r
+\r
+ }\r
\r
+ if (!config.isDeleteTaxonNodes() && (ref instanceof TaxonNode)){\r
+ message = "The Taxon can't be deleted as long as it belongs to a taxon node.";\r
\r
+ }\r
+ if (!config.isDeleteTaxonRelationships() && (ref instanceof TaxonNode)){\r
+ if (!config.isDeleteMisappliedNamesAndInvalidDesignations() && (((TaxonRelationship)ref).getType().equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())|| ((TaxonRelationship)ref).getType().equals(TaxonRelationshipType.INVALID_DESIGNATION_FOR()))){\r
+ message = "The Taxon can't be deleted as long as it has misapplied names or invalid designations.";\r
+\r
+ } else{\r
+ message = "The Taxon can't be deleted as long as it belongs to a taxon node.";\r
+\r
+ }\r
+ }\r
+ if (ref instanceof PolytomousKeyNode){\r
+ message = "The Taxon can't be deleted as long as it is referenced by a polytomous key node.";\r
+\r
+ }\r
+\r
+ if (HibernateProxyHelper.isInstanceOf(ref, IIdentificationKey.class)){\r
+ message = "Taxon can't be deleted as it is used in an identification key. Remove from identification key prior to deleting this name";\r
+\r
+\r
+ }\r
+\r
+\r
+ /* //PolytomousKeyNode\r
+ if (referencingObject.isInstanceOf(PolytomousKeyNode.class)){\r
+ String message = "Taxon" + taxon.getTitleCache() + " can't be deleted as it is used in polytomous key node";\r
+ return message;\r
+ }*/\r
+\r
+ //TaxonInteraction\r
+ if (ref.isInstanceOf(TaxonInteraction.class)){\r
+ message = "Taxon can't be deleted as it is used in taxonInteraction#taxon2";\r
+\r
+ }\r
+\r
+ //TaxonInteraction\r
+ if (ref.isInstanceOf(DeterminationEvent.class)){\r
+ message = "Taxon can't be deleted as it is used in a determination event";\r
+\r
+ }\r
+\r
+ }\r
+ if (message != null){\r
+ result.addException(new ReferencedObjectUndeletableException(message));\r
+ result.addRelatedObject(ref);\r
+ result.setAbort();\r
+ }\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public IncludedTaxaDTO listIncludedTaxa(UUID taxonUuid, IncludedTaxonConfiguration config) {\r
+ IncludedTaxaDTO result = new IncludedTaxaDTO(taxonUuid);\r
+\r
+ //preliminary implementation\r
+\r
+ Set<Taxon> taxa = new HashSet<Taxon>();\r
+ TaxonBase taxonBase = find(taxonUuid);\r
+ if (taxonBase == null){\r
+ return new IncludedTaxaDTO();\r
+ }else if (taxonBase.isInstanceOf(Taxon.class)){\r
+ Taxon taxon = CdmBase.deproxy(taxonBase, Taxon.class);\r
+ taxa.add(taxon);\r
+ }else if (taxonBase.isInstanceOf(Synonym.class)){\r
+ //TODO partial synonyms ??\r
+ //TODO synonyms in general\r
+ Synonym syn = CdmBase.deproxy(taxonBase, Synonym.class);\r
+ taxa.addAll(syn.getAcceptedTaxa());\r
+ }else{\r
+ throw new IllegalArgumentException("Unhandled class " + taxonBase.getClass().getSimpleName());\r
+ }\r
+\r
+ Set<Taxon> related = makeRelatedIncluded(taxa, result, config);\r
+ int i = 0;\r
+ while((! related.isEmpty()) && i++ < 100){ //to avoid\r
+ related = makeRelatedIncluded(related, result, config);\r
+ }\r
+\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Computes all children and conceptually congruent and included taxa and adds them to the existingTaxa\r
+ * data structure.\r
+ * @return the set of conceptually related taxa for further use\r
+ */\r
+ /**\r
+ * @param uncheckedTaxa\r
+ * @param existingTaxa\r
+ * @param config\r
+ * @return\r
+ */\r
+ private Set<Taxon> makeRelatedIncluded(Set<Taxon> uncheckedTaxa, IncludedTaxaDTO existingTaxa, IncludedTaxonConfiguration config) {\r
+\r
+ //children\r
+ Set<TaxonNode> taxonNodes = new HashSet<TaxonNode>();\r
+ for (Taxon taxon: uncheckedTaxa){\r
+ taxonNodes.addAll(taxon.getTaxonNodes());\r
+ }\r
+\r
+ Set<Taxon> children = new HashSet<Taxon>();\r
+ if (! config.onlyCongruent){\r
+ for (TaxonNode node: taxonNodes){\r
+ List<TaxonNode> childNodes = nodeService.loadChildNodesOfTaxonNode(node, null, true, false);\r
+ for (TaxonNode child : childNodes){\r
+ children.add(child.getTaxon());\r
+ }\r
+ }\r
+ children.remove(null); // just to be on the save side\r
+ }\r
+\r
+ Iterator<Taxon> it = children.iterator();\r
+ while(it.hasNext()){\r
+ UUID uuid = it.next().getUuid();\r
+ if (existingTaxa.contains(uuid)){\r
+ it.remove();\r
+ }else{\r
+ existingTaxa.addIncludedTaxon(uuid, new ArrayList<UUID>(), false);\r
+ }\r
+ }\r
+\r
+ //concept relations\r
+ Set<Taxon> uncheckedAndChildren = new HashSet<Taxon>(uncheckedTaxa);\r
+ uncheckedAndChildren.addAll(children);\r
+\r
+ Set<Taxon> relatedTaxa = makeConceptIncludedTaxa(uncheckedAndChildren, existingTaxa, config);\r
+\r
+\r
+ Set<Taxon> result = new HashSet<Taxon>(relatedTaxa);\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * Computes all conceptually congruent or included taxa and adds them to the existingTaxa data structure.\r
+ * @return the set of these computed taxa\r
+ */\r
+ private Set<Taxon> makeConceptIncludedTaxa(Set<Taxon> unchecked, IncludedTaxaDTO existingTaxa, IncludedTaxonConfiguration config) {\r
+ Set<Taxon> result = new HashSet<Taxon>();\r
+\r
+ for (Taxon taxon : unchecked){\r
+ Set<TaxonRelationship> fromRelations = taxon.getRelationsFromThisTaxon();\r
+ Set<TaxonRelationship> toRelations = taxon.getRelationsToThisTaxon();\r
+\r
+ for (TaxonRelationship fromRel : fromRelations){\r
+ if (config.includeDoubtful == false && fromRel.isDoubtful()){\r
+ continue;\r
+ }\r
+ if (fromRel.getType().equals(TaxonRelationshipType.CONGRUENT_TO()) ||\r
+ !config.onlyCongruent && fromRel.getType().equals(TaxonRelationshipType.INCLUDES()) ||\r
+ !config.onlyCongruent && fromRel.getType().equals(TaxonRelationshipType.CONGRUENT_OR_INCLUDES())\r
+ ){\r
+ result.add(fromRel.getToTaxon());\r
+ }\r
+ }\r
+\r
+ for (TaxonRelationship toRel : toRelations){\r
+ if (config.includeDoubtful == false && toRel.isDoubtful()){\r
+ continue;\r
+ }\r
+ if (toRel.getType().equals(TaxonRelationshipType.CONGRUENT_TO())){\r
+ result.add(toRel.getFromTaxon());\r
+ }\r
+ }\r
+ }\r
+\r
+ Iterator<Taxon> it = result.iterator();\r
+ while(it.hasNext()){\r
+ UUID uuid = it.next().getUuid();\r
+ if (existingTaxa.contains(uuid)){\r
+ it.remove();\r
+ }else{\r
+ existingTaxa.addIncludedTaxon(uuid, new ArrayList<UUID>(), false);\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public List<TaxonBase> findTaxaByName(MatchingTaxonConfigurator config){\r
+ List<TaxonBase> taxonList = dao.getTaxaByName(true, false, false, config.getTaxonNameTitle(), null, MatchMode.EXACT, null, 0, 0, config.getPropertyPath());\r
+ return taxonList;\r
+ }\r
+ \r
+ @Override\r
+ @Transactional(readOnly = true)\r
+ public <S extends TaxonBase> Pager<FindByIdentifierDTO<S>> findByIdentifier(\r
+ Class<S> clazz, String identifier, DefinedTerm identifierType, TaxonNode subtreeFilter,\r
+ MatchMode matchmode, boolean includeEntity, Integer pageSize,\r
+ Integer pageNumber, List<String> propertyPaths) {\r
+ if (subtreeFilter == null){\r
+ return findByIdentifier(clazz, identifier, identifierType, matchmode, includeEntity, pageSize, pageNumber, propertyPaths);\r
+ }\r
+ \r
+ Integer numberOfResults = dao.countByIdentifier(clazz, identifier, identifierType, subtreeFilter, matchmode);\r
+ List<Object[]> daoResults = new ArrayList<Object[]>();\r
+ if(numberOfResults > 0) { // no point checking again\r
+ daoResults = dao.findByIdentifier(clazz, identifier, identifierType, subtreeFilter,\r
+ matchmode, includeEntity, pageSize, pageNumber, propertyPaths);\r
+ }\r
+ \r
+ List<FindByIdentifierDTO<S>> result = new ArrayList<FindByIdentifierDTO<S>>();\r
+ for (Object[] daoObj : daoResults){\r
+ if (includeEntity){\r
+ result.add(new FindByIdentifierDTO<S>((DefinedTerm)daoObj[0], (String)daoObj[1], (S)daoObj[2]));\r
+ }else{\r
+ result.add(new FindByIdentifierDTO<S>((DefinedTerm)daoObj[0], (String)daoObj[1], (UUID)daoObj[2], (String)daoObj[3])); \r
+ }\r
+ }\r
+ return new DefaultPagerImpl<FindByIdentifierDTO<S>>(pageNumber, numberOfResults, pageSize, result);\r
+ }\r
\r
}\r