import java.util.HashMap;\r
import java.util.HashSet;\r
import java.util.List;\r
+import java.util.Map;\r
import java.util.Set;\r
import java.util.UUID;\r
\r
import org.apache.lucene.search.BooleanQuery;\r
import org.apache.lucene.search.Query;\r
import org.apache.lucene.search.SortField;\r
-import org.apache.lucene.search.TopDocs;\r
import org.springframework.beans.factory.annotation.Autowired;\r
import org.springframework.stereotype.Service;\r
import org.springframework.transaction.annotation.Propagation;\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.ISearchResultBuilder;\r
+import eu.etaxonomy.cdm.api.service.search.LuceneMultiSearch;\r
import eu.etaxonomy.cdm.api.service.search.LuceneSearch;\r
+import eu.etaxonomy.cdm.api.service.search.LuceneSearch.TopGroupsWithMaxScore;\r
import eu.etaxonomy.cdm.api.service.search.QueryFactory;\r
import eu.etaxonomy.cdm.api.service.search.SearchResult;\r
import eu.etaxonomy.cdm.api.service.search.SearchResultBuilder;\r
+import eu.etaxonomy.cdm.api.service.util.TaxonRelationshipEdge;\r
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;\r
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
import eu.etaxonomy.cdm.hibernate.search.DefinedTermBaseClassBridge;\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.IdentifiableEntity;\r
import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
import eu.etaxonomy.cdm.model.common.RelationshipBase;\r
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;\r
import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\r
+import eu.etaxonomy.cdm.model.description.DescriptionBase;\r
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\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.SpecimenDescription;\r
import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
import eu.etaxonomy.cdm.model.description.TaxonInteraction;\r
+import eu.etaxonomy.cdm.model.description.TaxonNameDescription;\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.DnaSample;\r
+import eu.etaxonomy.cdm.model.molecular.Sequence;\r
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;\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.DerivedUnitBase;\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.Synonym;\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.name.ITaxonNameDao;\r
+import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;\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 IOrderedTermVocabularyDao orderedVocabularyDao;\r
\r
+ @Autowired\r
+ private IOccurrenceDao occurrenceDao;\r
+\r
+ @Autowired\r
+ private AbstractBeanInitializer beanInitializer;\r
+\r
/**\r
* Constructor\r
*/\r
* FIXME Candidate for harmonization\r
* rename searchByName ?\r
*/\r
+ @Override\r
public List<TaxonBase> searchTaxaByName(String name, Reference sec) {\r
return dao.getTaxaByName(name, sec);\r
}\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
* (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
* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, boolean)\r
*/\r
+ @Override\r
public List<Taxon> getRootTaxa(Reference sec, CdmFetch cdmFetch, boolean onlyWithChildren) {\r
if (cdmFetch == null){\r
cdmFetch = CdmFetch.NO_FETCH();\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
/* (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
}\r
* FIXME Candidate for harmonization\r
* is this the same as termService.getVocabulary(VocabularyEnum.TaxonRelationshipType) ?\r
*/\r
+ @Override\r
@Deprecated\r
public OrderedTermVocabulary<TaxonRelationshipType> getTaxonRelationshipTypeVocabulary() {\r
\r
* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#swapSynonymWithAcceptedTaxon(eu.etaxonomy.cdm.model.taxon.Synonym)\r
*/\r
+ @Override\r
@Transactional(readOnly = false)\r
public void swapSynonymAndAcceptedTaxon(Synonym synonym, Taxon acceptedTaxon){\r
\r
}\r
\r
\r
+ @Override\r
public Taxon changeSynonymToRelatedTaxon(Synonym synonym, Taxon toTaxon, TaxonRelationshipType taxonRelationshipType, Reference citation, String microcitation){\r
\r
// Get name from synonym\r
super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);\r
}\r
\r
+ @Override\r
@Autowired\r
protected void setDao(ITaxonDao dao) {\r
this.dao = dao;\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, 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
/* (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
\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
\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
\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
\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
\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 Set<Taxon> listRelatedTaxa(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships, Integer maxDepth,\r
+ Integer limit, Integer start, List<String> propertyPaths) {\r
+\r
+ Set<Taxon> relatedTaxa = collectRelatedTaxa(taxon, includeRelationships, new HashSet<Taxon>(), maxDepth);\r
+ relatedTaxa.remove(taxon);\r
+ beanInitializer.initializeAll(relatedTaxa, propertyPaths);\r
+ return relatedTaxa;\r
+ }\r
+\r
+\r
+ /**\r
+ * recursively collect related taxa for the given <code>taxon</code> . The returned list will also include the\r
+ * <code>taxon</code> supplied as parameter.\r
+ *\r
+ * @param taxon\r
+ * @param includeRelationships\r
+ * @param taxa\r
+ * @param maxDepth can be <code>null</code> for infinite depth\r
+ * @return\r
+ */\r
+ private Set<Taxon> collectRelatedTaxa(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships, Set<Taxon> taxa, Integer maxDepth) {\r
+\r
+ if(taxa.isEmpty()) {\r
+ taxa.add(taxon);\r
+ }\r
+\r
+ if(maxDepth != null) {\r
+ maxDepth--;\r
+ }\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug("collecting related taxa for " + taxon + " with maxDepth=" + maxDepth);\r
+ }\r
+ List<TaxonRelationship> taxonRelationships = dao.getTaxonRelationships(taxon, null, null, null, null, null, null);\r
+ for (TaxonRelationship taxRel : taxonRelationships) {\r
+\r
+ // skip invalid data\r
+ if (taxRel.getToTaxon() == null || taxRel.getFromTaxon() == null || taxRel.getType() == null) {\r
+ continue;\r
+ }\r
+ // filter by includeRelationships\r
+ for (TaxonRelationshipEdge relationshipEdgeFilter : includeRelationships) {\r
+ if ( relationshipEdgeFilter.getTaxonRelationshipType().equals(taxRel.getType()) ) {\r
+ if (relationshipEdgeFilter.getDirections().contains(Direction.relatedTo) && !taxa.contains(taxRel.getToTaxon())) {\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug(maxDepth + ": " + taxon.getTitleCache() + " --[" + taxRel.getType().getLabel() + "]--> " + taxRel.getToTaxon().getTitleCache());\r
+ }\r
+ taxa.add(taxRel.getToTaxon());\r
+ if(maxDepth == null || maxDepth > 0) {\r
+ taxa.addAll(collectRelatedTaxa(taxRel.getToTaxon(), includeRelationships, taxa, maxDepth));\r
+ }\r
+ }\r
+ if(relationshipEdgeFilter.getDirections().contains(Direction.relatedFrom) && !taxa.contains(taxRel.getFromTaxon())) {\r
+ taxa.add(taxRel.getFromTaxon());\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug(maxDepth + ": " +taxRel.getFromTaxon().getTitleCache() + " --[" + taxRel.getType().getLabel() + "]--> " + taxon.getTitleCache() );\r
+ }\r
+ if(maxDepth == null || maxDepth > 0) {\r
+ taxa.addAll(collectRelatedTaxa(taxRel.getFromTaxon(), includeRelationships, taxa, maxDepth));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return taxa;\r
+ }\r
+\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getSynonyms(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public Pager<SynonymRelationship> getSynonyms(Taxon taxon, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countSynonyms(taxon, type);\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getSynonyms(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
*/\r
+ @Override\r
public Pager<SynonymRelationship> getSynonyms(Synonym synonym, SynonymRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Integer numberOfResults = dao.countSynonyms(synonym, type);\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<Synonym> getHomotypicSynonymsByHomotypicGroup(Taxon taxon, List<String> propertyPaths){\r
Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);\r
return t.getHomotypicSynonymsByHomotypicGroup();\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getHeterotypicSynonymyGroups(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.List)\r
*/\r
+ @Override\r
public List<List<Synonym>> getHeterotypicSynonymyGroups(Taxon taxon, List<String> propertyPaths){\r
Taxon t = (Taxon)dao.load(taxon.getUuid(), propertyPaths);\r
List<HomotypicalGroup> homotypicalGroups = t.getHeterotypicSynonymyGroups();\r
return heterotypicSynonymyGroups;\r
}\r
\r
+ @Override\r
public List<UuidAndTitleCache<TaxonBase>> findTaxaAndNamesForEditor(IFindTaxaAndNamesConfigurator configurator){\r
\r
List<UuidAndTitleCache<TaxonBase>> result = new ArrayList<UuidAndTitleCache<TaxonBase>>();\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaAndNames(eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator)\r
*/\r
+ @Override\r
public Pager<IdentifiableEntity> findTaxaAndNames(IFindTaxaAndNamesConfigurator configurator) {\r
\r
List<IdentifiableEntity> results = new ArrayList<IdentifiableEntity>();\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getAllMedia(eu.etaxonomy.cdm.model.taxon.Taxon, int, int, int, java.lang.String[])\r
*/\r
+ @Override\r
public List<MediaRepresentation> getAllMedia(Taxon taxon, int size, int height, int widthOrDuration, String[] mimeTypes){\r
List<MediaRepresentation> medRep = new ArrayList<MediaRepresentation>();\r
taxon = (Taxon)dao.load(taxon.getUuid());\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#listTaxonDescriptionMedia(eu.etaxonomy.cdm.model.taxon.Taxon, boolean)\r
*/\r
- public List<Media> listTaxonDescriptionMedia(Taxon taxon, boolean limitToGalleries, List<String> propertyPath){\r
-\r
- Pager<TaxonDescription> p =\r
- descriptionService.getTaxonDescriptions(taxon, null, null, null, null, propertyPath);\r
+ @Override\r
+ public List<Media> listTaxonDescriptionMedia(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships, boolean limitToGalleries, List<String> propertyPath){\r
+ return listMedia(taxon, includeRelationships, limitToGalleries, true, false, false, propertyPath);\r
+ }\r
\r
- // pars the media and quality parameters\r
\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#listMedia(eu.etaxonomy.cdm.model.taxon.Taxon, java.util.Set, boolean, java.util.List)\r
+ */\r
+ @Override\r
+ public List<Media> listMedia(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships,\r
+ Boolean limitToGalleries, Boolean includeTaxonDescriptions, Boolean includeOccurrences,\r
+ Boolean includeTaxonNameDescriptions, List<String> propertyPath) {\r
\r
- // collect all media of the given taxon\r
+ Set<Taxon> taxa = new HashSet<Taxon>();\r
List<Media> taxonMedia = new ArrayList<Media>();\r
- List<Media> taxonGalleryMedia = new ArrayList<Media>();\r
- for(TaxonDescription desc : p.getRecords()){\r
\r
- if(desc.isImageGallery()){\r
- for(DescriptionElementBase element : desc.getElements()){\r
- for(Media media : element.getMedia()){\r
- taxonGalleryMedia.add(media);\r
+ if (limitToGalleries == null) {\r
+ limitToGalleries = false;\r
+ }\r
+\r
+ // --- resolve related taxa\r
+ if (includeRelationships != null) {\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
+ List<TaxonDescription> taxonDescriptions = new ArrayList<TaxonDescription>();\r
+ // --- TaxonDescriptions\r
+ for (Taxon t : taxa) {\r
+ taxonDescriptions.addAll(descriptionService.listTaxonDescriptions(t, null, null, null, null, propertyPath));\r
+ }\r
+ for (TaxonDescription taxonDescription : taxonDescriptions) {\r
+ if (!limitToGalleries || taxonDescription.isImageGallery()) {\r
+ for (DescriptionElementBase element : taxonDescription.getElements()) {\r
+ for (Media media : element.getMedia()) {\r
+ taxonMedia.add(media);\r
+ }\r
}\r
}\r
- } else if(!limitToGalleries){\r
- for(DescriptionElementBase element : desc.getElements()){\r
- for(Media media : element.getMedia()){\r
- taxonMedia.add(media);\r
+ }\r
+ }\r
+\r
+ if(includeOccurrences != null && includeOccurrences) {\r
+ Set<SpecimenOrObservationBase> specimensOrObservations = new HashSet<SpecimenOrObservationBase>();\r
+ // --- Specimens\r
+ for (Taxon t : taxa) {\r
+ specimensOrObservations.addAll(occurrenceDao.listByAssociatedTaxon(null, t, null, null, null, null));\r
+ }\r
+ for (SpecimenOrObservationBase occurrence : specimensOrObservations) {\r
+\r
+ taxonMedia.addAll(occurrence.getMedia());\r
+\r
+ // SpecimenDescriptions\r
+ Set<SpecimenDescription> specimenDescriptions = occurrence.getSpecimenDescriptions();\r
+ for (DescriptionBase specimenDescription : specimenDescriptions) {\r
+ if (!limitToGalleries || specimenDescription.isImageGallery()) {\r
+ Set<DescriptionElementBase> elements = specimenDescription.getElements();\r
+ for (DescriptionElementBase element : elements) {\r
+ for (Media media : element.getMedia()) {\r
+ taxonMedia.add(media);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // Collection\r
+ if (occurrence instanceof DerivedUnitBase) {\r
+ if (((DerivedUnitBase) occurrence).getCollection() != null){\r
+ taxonMedia.addAll(((DerivedUnitBase) occurrence).getCollection().getMedia());\r
+ }\r
+ }\r
+\r
+ // Chromatograms\r
+ if (occurrence instanceof DnaSample) {\r
+ Set<Sequence> sequences = ((DnaSample) occurrence).getSequences();\r
+ for (Sequence sequence : sequences) {\r
+ taxonMedia.addAll(sequence.getChromatograms());\r
}\r
}\r
+\r
}\r
+ }\r
\r
+ if(includeTaxonNameDescriptions != null && includeTaxonNameDescriptions) {\r
+ // --- TaxonNameDescription\r
+ Set<TaxonNameDescription> nameDescriptions = new HashSet<TaxonNameDescription>();\r
+ for (Taxon t : taxa) {\r
+ nameDescriptions .addAll(t.getName().getDescriptions());\r
+ }\r
+ for(TaxonNameDescription nameDescription: nameDescriptions){\r
+ if (!limitToGalleries || nameDescription.isImageGallery()) {\r
+ Set<DescriptionElementBase> elements = nameDescription.getElements();\r
+ for (DescriptionElementBase element : elements) {\r
+ for (Media media : element.getMedia()) {\r
+ taxonMedia.add(media);\r
+ }\r
+ }\r
+ }\r
+ }\r
}\r
\r
- taxonGalleryMedia.addAll(taxonMedia);\r
- return taxonGalleryMedia;\r
+ beanInitializer.initializeAll(taxonMedia, propertyPath);\r
+ return taxonMedia;\r
}\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxaByID(java.util.Set)\r
*/\r
+ @Override\r
public List<TaxonBase> findTaxaByID(Set<Integer> listOfIDs) {\r
- return this.dao.findById(listOfIDs);\r
+ return this.dao.listByIds(listOfIDs, null, null, null, null);\r
}\r
\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findTaxonByUuid(UUID uuid, List<String> propertyPaths)\r
*/\r
+ @Override\r
public TaxonBase findTaxonByUuid(UUID uuid, List<String> propertyPaths){\r
return this.dao.findByUuid(uuid, null ,propertyPaths);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#countAllRelationships()\r
*/\r
+ @Override\r
public int countAllRelationships() {\r
return this.dao.countAllRelationships();\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNames(java.util.List)\r
*/\r
+ @Override\r
public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPath) {\r
return this.dao.findIdenticalTaxonNames(propertyPath);\r
}\r
try{\r
nameService.delete(name, new NameDeletionConfigurator());\r
}catch (DataChangeNoRollbackException ex){\r
- if (logger.isDebugEnabled())logger.debug("Name wasn't deleted as it is referenced");\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Name wasn't deleted as it is referenced");\r
+ }\r
}\r
}\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#findIdenticalTaxonNameIds(java.util.List)\r
*/\r
+ @Override\r
public List<TaxonNameBase> findIdenticalTaxonNameIds(List<String> propertyPath) {\r
\r
return this.dao.findIdenticalNamesNew(propertyPath);\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#getPhylumName(eu.etaxonomy.cdm.model.name.TaxonNameBase)\r
*/\r
+ @Override\r
public String getPhylumName(TaxonNameBase name){\r
return this.dao.getPhylumName(name);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym, eu.etaxonomy.cdm.model.taxon.Taxon)\r
*/\r
+ @Override\r
public long deleteSynonymRelationships(Synonym syn, Taxon taxon) {\r
return dao.deleteSynonymRelationships(syn, taxon);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#deleteSynonymRelationships(eu.etaxonomy.cdm.model.taxon.Synonym)\r
*/\r
+ @Override\r
public long deleteSynonymRelationships(Synonym syn) {\r
return dao.deleteSynonymRelationships(syn, null);\r
}\r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.api.service.ITaxonService#listSynonymRelationships(eu.etaxonomy.cdm.model.taxon.TaxonBase, eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List, eu.etaxonomy.cdm.model.common.RelationshipBase.Direction)\r
*/\r
+ @Override\r
public List<SynonymRelationship> listSynonymRelationships(\r
TaxonBase taxonBase, SynonymRelationshipType type, Integer pageSize, Integer pageNumber,\r
List<OrderHint> orderHints, List<String> propertyPaths, Direction direction) {\r
return dao.getUuidAndTitleCacheSynonym();\r
}\r
\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#findByFullText(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, java.util.List, boolean, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
+ */\r
@Override\r
public Pager<SearchResult<TaxonBase>> findByFullText(\r
Class<? extends TaxonBase> clazz, String queryString,\r
Classification classification, List<Language> languages,\r
boolean highlightFragments, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
\r
-// // -- set defaults\r
-// Class<? extends TaxonBase> directorySelectClass = TaxonBase.class;\r
-// if(clazz != null){\r
-// directorySelectClass = clazz;\r
-// }\r
- return null;\r
\r
+ LuceneSearch luceneSearch = prepareFindByFullTextSearch(clazz, queryString, classification, languages, highlightFragments);\r
+\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = luceneSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+\r
+ // --- initialize taxa, thighlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, luceneSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupedHitCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
}\r
\r
+ /**\r
+ * @param clazz\r
+ * @param queryString\r
+ * @param classification\r
+ * @param languages\r
+ * @param highlightFragments\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
+ BooleanQuery finalQuery = new BooleanQuery();\r
+ BooleanQuery textQuery = new BooleanQuery();\r
+\r
+ LuceneSearch luceneSearch = new LuceneSearch(getSession(), TaxonBase.class);\r
+ QueryFactory queryFactory = new QueryFactory(luceneSearch);\r
+\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("titleCache__sort", false)};\r
+ luceneSearch.setSortFields(sortFields);\r
+\r
+ // ---- search criteria\r
+ luceneSearch.setClazz(clazz);\r
+\r
+ textQuery.add(queryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
+ textQuery.add(queryFactory.newDefinedTermQuery("name.rank", queryString, languages), Occur.SHOULD);\r
+\r
+ finalQuery.add(textQuery, Occur.MUST);\r
+\r
+ if(classification != null){\r
+ finalQuery.add(queryFactory.newEntityIdQuery("taxonNodes.classification.id", classification), Occur.MUST);\r
+ }\r
+ luceneSearch.setQuery(finalQuery);\r
+\r
+ if(highlightFragments){\r
+ luceneSearch.setHighlightFields(queryFactory.getTextFieldNamesAsArray());\r
+ }\r
+ return luceneSearch;\r
+ }\r
+\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.api.service.ITaxonService#findByDescriptionElementFullText(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, java.util.List, java.util.List, boolean, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
+ */\r
@Override\r
public Pager<SearchResult<TaxonBase>> findByDescriptionElementFullText(\r
Class<? extends DescriptionElementBase> clazz, String queryString,\r
Classification classification, List<Feature> features, List<Language> languages,\r
boolean highlightFragments, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
\r
- // -- set defaults\r
- Class<? extends DescriptionElementBase> directorySelectClass = DescriptionElementBase.class;\r
- if(clazz != null){\r
- directorySelectClass = clazz;\r
- }\r
\r
-// queryString = queryString.toLowerCase();\r
+ LuceneSearch luceneSearch = prepareByDescriptionElementFullTextSearch(clazz, queryString, classification, features, languages, highlightFragments);\r
+\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = luceneSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+ idFieldMap.put(CdmBaseType.DESCRIPTION_ELEMENT, "inDescription.taxon.id");\r
+\r
+ // --- initialize taxa, highlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, luceneSearch.getQuery());\r
+ @SuppressWarnings("rawtypes")\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, luceneSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
+\r
+ }\r
+\r
+\r
+ @Override\r
+ public Pager<SearchResult<TaxonBase>> findByEverythingFullText(String queryString,\r
+ Classification classification, List<Language> languages, boolean highlightFragments,\r
+ Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws CorruptIndexException, IOException, ParseException {\r
+\r
+ LuceneSearch luceneSearchByDescriptionElement = prepareByDescriptionElementFullTextSearch(null, queryString, classification, null, languages, highlightFragments);\r
+ LuceneSearch luceneSearchByTaxonBase = prepareFindByFullTextSearch(null, queryString, classification, languages, highlightFragments);\r
+\r
+ LuceneMultiSearch multiSearch = new LuceneMultiSearch(luceneSearchByDescriptionElement, luceneSearchByTaxonBase);\r
+\r
+ // --- execute search\r
+ TopGroupsWithMaxScore topDocsResultSet = multiSearch.executeSearch(pageSize, pageNumber);\r
+\r
+ // --- initialize taxa, highlight matches ....\r
+ ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(multiSearch, multiSearch.getQuery());\r
+\r
+ Map<CdmBaseType, String> idFieldMap = new HashMap<CdmBaseType, String>();\r
+ idFieldMap.put(CdmBaseType.TAXON, "id");\r
+ idFieldMap.put(CdmBaseType.DESCRIPTION_ELEMENT, "inDescription.taxon.id");\r
+\r
+ List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
+ topDocsResultSet, multiSearch.getHighlightFields(), dao, idFieldMap, propertyPaths);\r
+\r
+ int totalHits = topDocsResultSet != null ? topDocsResultSet.topGroups.totalGroupedHitCount : 0;\r
+ return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, totalHits, pageSize, searchResults);\r
+\r
+ }\r
+\r
\r
- StringBuilder luceneQueryTemplate = new StringBuilder();\r
+ /**\r
+ * @param clazz\r
+ * @param queryString\r
+ * @param classification\r
+ * @param features\r
+ * @param languages\r
+ * @param highlightFragments\r
+ * @param directorySelectClass\r
+ * @return\r
+ */\r
+ protected LuceneSearch prepareByDescriptionElementFullTextSearch(Class<? extends CdmBase> clazz, String queryString, Classification classification, List<Feature> features,\r
+ List<Language> languages, boolean highlightFragments) {\r
BooleanQuery finalQuery = new BooleanQuery();\r
BooleanQuery textQuery = new BooleanQuery();\r
- Set<String> freetextFields = new HashSet<String>();\r
\r
- LuceneSearch luceneSearch = new LuceneSearch(getSession(), directorySelectClass);\r
- QueryFactory queryBuilder = new QueryFactory(luceneSearch);\r
+ LuceneSearch luceneSearch = new LuceneSearch(getSession(), DescriptionElementBase.class);\r
+ QueryFactory queryFactory = new QueryFactory(luceneSearch);\r
\r
- // ---- search criteria\r
+ SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("inDescription.taxon.titleCache__sort", false)};\r
+ luceneSearch.setSortFields(sortFields);\r
\r
-// luceneQueryTemplate.append("+(");\r
-// luceneQueryTemplate.append("titleCache:(%1$s) ");\r
- freetextFields.add("titleCache");\r
- textQuery.add(queryBuilder.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
+ // ---- search criteria\r
+ luceneSearch.setClazz(clazz);\r
+ textQuery.add(queryFactory.newTermQuery("titleCache", queryString), Occur.SHOULD);\r
\r
// common name\r
- freetextFields.add("name");\r
-\r
Query nameQuery;\r
if(languages == null || languages.size() == 0){\r
-// luceneQueryTemplate.append("name:(%1$s) ");\r
- nameQuery = queryBuilder.newTermQuery("name", queryString);\r
+ nameQuery = queryFactory.newTermQuery("name", queryString);\r
} else {\r
nameQuery = new BooleanQuery();\r
BooleanQuery languageSubQuery = new BooleanQuery();\r
-// luceneQueryTemplate.append("(+name:(%1$s) ");\r
for(Language lang : languages){\r
-// luceneQueryTemplate.append(" +language.uuid:" + lang.getUuid().toString());\r
- languageSubQuery.add(queryBuilder.newTermQuery("language.uuid", lang.getUuid().toString()), Occur.SHOULD);\r
+ languageSubQuery.add(queryFactory.newTermQuery("language.uuid", lang.getUuid().toString()), Occur.SHOULD);\r
}\r
- ((BooleanQuery) nameQuery).add(queryBuilder.newTermQuery("name", queryString), Occur.MUST);\r
+ ((BooleanQuery) nameQuery).add(queryFactory.newTermQuery("name", queryString), Occur.MUST);\r
((BooleanQuery) nameQuery).add(languageSubQuery, Occur.MUST);\r
-// luceneQueryTemplate.append(")");\r
}\r
textQuery.add(nameQuery, Occur.SHOULD);\r
\r
\r
// text field from TextData\r
- freetextFields.add("text.ALL");\r
-// appendLocalizedFieldQuery("text", languages, luceneQueryTemplate).append(" ");\r
- textQuery.add(queryBuilder.newLocalizedTermQuery("text", queryString, languages), Occur.SHOULD);\r
+ textQuery.add(queryFactory.newMultilanguageTextQuery("text", queryString, languages), Occur.SHOULD);\r
\r
// --- TermBase fields - by representation ----\r
// state field from CategoricalData\r
- freetextFields.add("states.state.representation.ALL");\r
-// appendLocalizedFieldQuery("states.state.representation", languages, luceneQueryTemplate).append(" ");\r
- textQuery.add(queryBuilder.newLocalizedTermQuery("states.state.representation", queryString, languages), Occur.SHOULD);\r
+ textQuery.add(queryFactory.newDefinedTermQuery("states.state", queryString, languages), Occur.SHOULD);\r
\r
// state field from CategoricalData\r
- freetextFields.add("states.modifyingText.ALL");\r
-// appendLocalizedFieldQuery("states.modifyingText", languages, luceneQueryTemplate).append(" ");\r
- textQuery.add(queryBuilder.newLocalizedTermQuery("states.modifyingText", queryString, languages), Occur.SHOULD);\r
-// luceneQueryTemplate.append(") ");\r
+ textQuery.add(queryFactory.newDefinedTermQuery("states.modifyingText", queryString, languages), Occur.SHOULD);\r
+\r
+ // area field from Distribution\r
+ textQuery.add(queryFactory.newDefinedTermQuery("area", queryString, languages), Occur.SHOULD);\r
+\r
+ // status field from Distribution\r
+ textQuery.add(queryFactory.newDefinedTermQuery("status", queryString, languages), Occur.SHOULD);\r
\r
finalQuery.add(textQuery, Occur.MUST);\r
// --- classification ----\r
\r
if(classification != null){\r
-// luceneQueryTemplate.append("+inDescription.taxon.taxonNodes.classification.id:").append(PaddedIntegerBridge.paddInteger(classification.getId())).append(" ");\r
- finalQuery.add(queryBuilder.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification), Occur.MUST);\r
+ finalQuery.add(queryFactory.newEntityIdQuery("inDescription.taxon.taxonNodes.classification.id", classification), Occur.MUST);\r
}\r
\r
// --- IdentifieableEntity fields - by uuid\r
if(features != null && features.size() > 0 ){\r
- finalQuery.add(queryBuilder.newEntityUuidQuery("feature.uuid", features), Occur.MUST);\r
-// luceneQueryTemplate.append("+feature.uuid:(");\r
-// for(Feature feature : features){\r
-// luceneQueryTemplate.append(feature.getUuid()).append(" ");\r
-// }\r
-// luceneQueryTemplate.append(") ");\r
+ finalQuery.add(queryFactory.newEntityUuidQuery("feature.uuid", features), Occur.MUST);\r
}\r
\r
// the description must be associated with a taxon\r
-// luceneQueryTemplate.append("+inDescription.taxon.id:[ " + PaddedIntegerBridge.paddInteger(0) + " TO " + PaddedIntegerBridge.paddInteger(Integer.MAX_VALUE) + "] ");\r
- //luceneQueryTemplate.append("-inDescription.taxon.id:" + PaddedIntegerBridge.NULL_STRING);\r
- finalQuery.add(queryBuilder.newIdNotNullQuery("inDescription.taxon.id"), Occur.MUST);\r
-\r
-// String luceneQueryStr = String.format(luceneQueryTemplate.toString(), queryString);\r
-\r
- // --- sort fields\r
- SortField[] sortFields = new SortField[]{SortField.FIELD_SCORE, new SortField("inDescription.taxon.titleCache__sort", false)};\r
-\r
- // ---- execute criteria\r
+ finalQuery.add(queryFactory.newIsNotNullQuery("inDescription.taxon.id"), Occur.MUST);\r
\r
+ luceneSearch.setQuery(finalQuery);\r
\r
-// Query luceneQuery = luceneSearch.parse(luceneQueryStr);\r
- TopDocs topDocsResultSet = luceneSearch.executeSearch(finalQuery, clazz, pageSize, pageNumber, sortFields);\r
-\r
- String[] highlightFields = null;\r
if(highlightFragments){\r
- highlightFields = freetextFields.toArray(new String[freetextFields.size()]);\r
+ luceneSearch.setHighlightFields(queryFactory.getTextFieldNamesAsArray());\r
}\r
-\r
- // initialize taxa, thighlight matches ....\r
- ISearchResultBuilder searchResultBuilder = new SearchResultBuilder(luceneSearch, finalQuery);\r
- List<SearchResult<TaxonBase>> searchResults = searchResultBuilder.createResultSet(\r
- topDocsResultSet, highlightFields, dao, "inDescription.taxon.id", propertyPaths);\r
-\r
- return new DefaultPagerImpl<SearchResult<TaxonBase>>(pageNumber, searchResults.size(), pageSize, searchResults);\r
-\r
+ return luceneSearch;\r
}\r
\r
/**\r
return stringBuilder;\r
}\r
\r
+ @Override\r
public List<Synonym> createInferredSynonyms(Taxon taxon, Classification classification, SynonymRelationshipType type, boolean doWithMisappliedNames){\r
List <Synonym> inferredSynonyms = new ArrayList<Synonym>();\r
List<Synonym> inferredSynonymsToBeRemoved = new ArrayList<Synonym>();\r
\r
if (node.getClassification().equals(classification)){\r
if (!node.isTopmostNode()){\r
- TaxonNode parent = (TaxonNode)node.getParent();\r
+ TaxonNode parent = node.getParent();\r
parent = (TaxonNode)HibernateProxyHelper.deproxy(parent);\r
TaxonNameBase parentName = parent.getTaxon().getName();\r
ZoologicalName zooParentName = HibernateProxyHelper.deproxy(parentName, ZoologicalName.class);\r
return citation;\r
}\r
\r
+ @Override\r
public List<Synonym> createAllInferredSynonyms(Taxon taxon, Classification tree, boolean doWithMisappliedNames){\r
List <Synonym> inferredSynonyms = new ArrayList<Synonym>();\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
+ // TODO quickly implemented, create according dao !!!!\r
+ Set<TaxonNode> nodes = new HashSet<TaxonNode>();\r
+ Set<Classification> classifications = new HashSet<Classification>();\r
+ List<Classification> list = new ArrayList<Classification>();\r
+\r
+ if (taxonBase == null) {\r
+ return list;\r
+ }\r
+\r
+ taxonBase = load(taxonBase.getUuid());\r
+\r
+ if (taxonBase instanceof Taxon) {\r
+ nodes.addAll(((Taxon)taxonBase).getTaxonNodes());\r
+ } else {\r
+ for (Taxon taxon : ((Synonym)taxonBase).getAcceptedTaxa() ) {\r
+ nodes.addAll(taxon.getTaxonNodes());\r
+ }\r
+ }\r
+ for (TaxonNode node : nodes) {\r
+ classifications.add(node.getClassification());\r
+ }\r
+ list.addAll(classifications);\r
+ return list;\r
+ }\r
+\r
+\r
+\r
\r
\r
\r