- refactored DTO assembly for compressed specimen table in the data portal
authorPatric Plitzner <p.plitzner@bgbm.org>
Fri, 27 Mar 2015 10:40:23 +0000 (10:40 +0000)
committerPatric Plitzner <p.plitzner@bgbm.org>
Fri, 27 Mar 2015 10:40:23 +0000 (10:40 +0000)
  - now data is assembled for each individual preserved specimen and the for the parent field unit

.gitattributes
cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/controller/OccurrencePortalController.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IOccurrenceService.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/OccurrenceServiceImpl.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateDTO.java [new file with mode: 0644]
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateDataDTO.java [moved from cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateHierarchyDTO.java with 50% similarity]
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/FieldUnitDTO.java [new file with mode: 0644]
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/PreservedSpecimenDTO.java [new file with mode: 0644]

index cbb01c076a66e6d9851069aad97a18705ea4d77a..8f76838f626b58e7719ef7349b7ff8b08343e068 100644 (file)
@@ -2321,10 +2321,13 @@ cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/config/TaxonDeletionC
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/config/TaxonNodeDeletionConfigurator.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/config/TermDeletionConfigurator.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/description/TransmissionEngineDistribution.java -text
-cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateHierarchyDTO.java -text
+cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateDTO.java -text
+cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateDataDTO.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DistributionInfoDTO.java -text
+cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/FieldUnitDTO.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/FindByIdentifierDTO.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/IncludedTaxaDTO.java -text
+cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/PreservedSpecimenDTO.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/exception/DataChangeNoRollbackException.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/exception/HomotypicalGroupChangeException.java -text
 cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/exception/ReferencedObjectUndeletableException.java -text
index d5ca970b453d5f4a929fdb19b5cbe264fc866962..2c8d0d6206f5ef1883900aba70c55b647d87e75a 100644 (file)
@@ -29,7 +29,8 @@ import org.springframework.web.servlet.ModelAndView;
 import com.wordnik.swagger.annotations.Api;\r
 \r
 import eu.etaxonomy.cdm.api.service.IOccurrenceService;\r
-import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.FieldUnitDTO;\r
 import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;\r
 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;\r
@@ -118,7 +119,7 @@ public class OccurrencePortalController extends BaseController<SpecimenOrObserva
 \r
         SpecimenOrObservationBase sob = service.load(uuid);\r
         if(sob instanceof FieldUnit){\r
-            final DerivateHierarchyDTO assembleDerivateHierarchyDTO = service.assembleDerivateHierarchyDTO((FieldUnit)sob, taxonUuid);\r
+            final FieldUnitDTO assembleDerivateHierarchyDTO = service.assembleFieldUnitDTO((FieldUnit)sob, taxonUuid);\r
             if(assembleDerivateHierarchyDTO!=null){\r
                 mv.addObject(assembleDerivateHierarchyDTO);\r
             }\r
index 5f8506f8cf56550203f67b9ba5c35a2fc0270d4c..4d29cdf3b86cf4f04b93b0de22b14ff2774357a0 100644 (file)
@@ -23,7 +23,9 @@ import org.hibernate.search.spatial.impl.Rectangle;
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;\r
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeNotSupportedException;\r
 import eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator;\r
-import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.PreservedSpecimenDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.FieldUnitDTO;\r
 import eu.etaxonomy.cdm.api.service.pager.Pager;\r
 import eu.etaxonomy.cdm.api.service.search.SearchResult;\r
 import eu.etaxonomy.cdm.api.service.util.TaxonRelationshipEdge;\r
@@ -32,6 +34,7 @@ import eu.etaxonomy.cdm.model.common.ICdmBase;
 import eu.etaxonomy.cdm.model.common.Language;\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.IndividualsAssociation;\r
 import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
 import eu.etaxonomy.cdm.model.location.Country;\r
@@ -323,14 +326,21 @@ public interface IOccurrenceService extends IIdentifiableEntityService<SpecimenO
     public boolean moveDerivate(SpecimenOrObservationBase<?> from, SpecimenOrObservationBase<?> to, DerivedUnit derivate);\r
 \r
     /**\r
-     * Assembles a {@link DerivateHierarchyDTO} for the given field unit uuid which is associated to the {@link Taxon}.<br>\r
+     * Assembles a {@link FieldUnitDTO} for the given field unit uuid which is associated to the {@link Taxon}.<br>\r
      * <br>\r
      * For the meaning of "associated" see also {@link #listFieldUnitsByAssociatedTaxon(Set, Taxon, Integer, Integer, Integer, List, List)}\r
      * @param fieldUnit\r
      * @param associatedTaxonUuid\r
-     * @return\r
+     * @return a DTO with all the assembled information\r
+     */\r
+    public FieldUnitDTO assembleFieldUnitDTO(FieldUnit fieldUnit, UUID associatedTaxonUuid);\r
+\r
+    /**\r
+     * Assembles a {@link PreservedSpecimenDTO} for the given derived unit.\r
+     * @param derivedUnit\r
+     * @return a DTO with all the assembled information\r
      */\r
-    public DerivateHierarchyDTO assembleDerivateHierarchyDTO(FieldUnit fieldUnit, UUID associatedTaxonUuid);\r
+    public PreservedSpecimenDTO assemblePreservedSpecimenDTO(DerivedUnit derivedUnit);\r
 \r
     /**\r
      * Returns a collection of {@link ICdmBase}s that are not persisted via cascading when saving the given specimen (mostly DefinedTerms).\r
@@ -389,4 +399,29 @@ public interface IOccurrenceService extends IIdentifiableEntityService<SpecimenO
      * @return collection of all descriptions with the given described specimen\r
      */\r
     public Collection<DescriptionBase<?>> listDescriptionsWithDescriptionSpecimen(SpecimenOrObservationBase<?> specimen, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
+\r
+    /**\r
+     * Gets all description elements that are used for describing the character\r
+     * states of the given specimen\r
+     *\r
+     * @param specimen\r
+     *            the specimen for which the character state description\r
+     *            elements should be retrieved\r
+     * @return a collection of all character state description elements for this\r
+     *         specimen\r
+     */\r
+    public Collection<DescriptionElementBase> getCharacterDataForSpecimen(SpecimenOrObservationBase<?> specimen);\r
+\r
+    /**\r
+     * Gets all description elements that are used for describing the character\r
+     * states of the given specimen\r
+     *\r
+     * @param specimenUuid\r
+     *            the specimen {@link UUID} for which the character state description\r
+     *            elements should be retrieved\r
+     * @return a collection of all character state description elements for this\r
+     *         specimen\r
+     */\r
+    public Collection<DescriptionElementBase> getCharacterDataForSpecimen(UUID specimenUuid);\r
+\r
 }\r
index f7e46a240df66139ae5412a7a9b82015ad1b61bd..e4c16eb5f0caa0a7edb8b06c200efae24943e3e5 100644 (file)
@@ -16,6 +16,7 @@ import java.net.URISyntaxException;
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
 import java.util.Collection;\r
+import java.util.Collections;\r
 import java.util.HashMap;\r
 import java.util.HashSet;\r
 import java.util.List;\r
@@ -34,6 +35,7 @@ import org.hibernate.TransientObjectException;
 import org.hibernate.search.spatial.impl.Rectangle;\r
 import org.joda.time.Partial;\r
 import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.dao.DataRetrievalFailureException;\r
 import org.springframework.stereotype.Service;\r
 import org.springframework.transaction.annotation.Transactional;\r
 \r
@@ -43,9 +45,12 @@ import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeNotSupportedException;
 import eu.etaxonomy.cdm.api.service.UpdateResult.Status;\r
 import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;\r
 import eu.etaxonomy.cdm.api.service.config.SpecimenDeleteConfigurator;\r
-import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO;\r
-import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO.ContigFile;\r
-import eu.etaxonomy.cdm.api.service.dto.DerivateHierarchyDTO.MolecularData;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateDataDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateDataDTO.ContigFile;\r
+import eu.etaxonomy.cdm.api.service.dto.DerivateDataDTO.MolecularData;\r
+import eu.etaxonomy.cdm.api.service.dto.FieldUnitDTO;\r
+import eu.etaxonomy.cdm.api.service.dto.PreservedSpecimenDTO;\r
 import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;\r
 import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;\r
 import eu.etaxonomy.cdm.api.service.pager.Pager;\r
@@ -68,9 +73,11 @@ import eu.etaxonomy.cdm.model.common.DefinedTermBase;
 import eu.etaxonomy.cdm.model.common.ICdmBase;\r
 import eu.etaxonomy.cdm.model.common.Language;\r
 import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\r
+import eu.etaxonomy.cdm.model.description.CategoricalData;\r
 import eu.etaxonomy.cdm.model.description.DescriptionBase;\r
 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;\r
+import eu.etaxonomy.cdm.model.description.QuantitativeData;\r
 import eu.etaxonomy.cdm.model.description.SpecimenDescription;\r
 import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
 import eu.etaxonomy.cdm.model.location.Country;\r
@@ -85,7 +92,6 @@ import eu.etaxonomy.cdm.model.molecular.Sequence;
 import eu.etaxonomy.cdm.model.molecular.SingleRead;\r
 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;\r
 import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
-import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;\r
 import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;\r
 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
 import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
@@ -338,91 +344,180 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase<SpecimenOrObs
     }\r
 \r
     @Override\r
-    public DerivateHierarchyDTO assembleDerivateHierarchyDTO(FieldUnit fieldUnit, UUID associatedTaxonUuid){\r
+    public FieldUnitDTO assembleFieldUnitDTO(FieldUnit fieldUnit, UUID associatedTaxonUuid){\r
 \r
         if(!getSession().contains(fieldUnit)){\r
             fieldUnit = (FieldUnit) load(fieldUnit.getUuid());\r
         }\r
         TaxonBase associatedTaxon = taxonService.load(associatedTaxonUuid);\r
 \r
-        DerivateHierarchyDTO dto = new DerivateHierarchyDTO();\r
-        Map<UUID, TypeDesignationStatusBase> typeSpecimenUUIDtoTypeDesignationStatus = new HashMap<UUID, TypeDesignationStatusBase>();\r
-\r
-        //gather types for this taxon name\r
-        TaxonNameBase<?,?> name = associatedTaxon.getName();\r
-        Set<?> typeDesignations = name.getSpecimenTypeDesignations();\r
-        for (Object object : typeDesignations) {\r
-            if(object instanceof CdmBase && ((CdmBase)object).isInstanceOf(SpecimenTypeDesignation.class)){\r
-                SpecimenTypeDesignation specimenTypeDesignation = HibernateProxyHelper.deproxy(object, SpecimenTypeDesignation.class);\r
-                DerivedUnit typeSpecimen = specimenTypeDesignation.getTypeSpecimen();\r
-                final TypeDesignationStatusBase typeStatus = specimenTypeDesignation.getTypeStatus();\r
-                typeSpecimenUUIDtoTypeDesignationStatus.put(typeSpecimen.getUuid(), typeStatus);\r
-            }\r
-        }\r
+        FieldUnitDTO fieldUnitDTO = new FieldUnitDTO();\r
 \r
         if(fieldUnit.getGatheringEvent()!=null){\r
             GatheringEvent gatheringEvent = fieldUnit.getGatheringEvent();\r
             //Country\r
             final NamedArea country = gatheringEvent.getCountry();\r
-            dto.setCountry(country!=null?country.getDescription():"");\r
+            fieldUnitDTO.setCountry(country!=null?country.getDescription():"");\r
             //Collection\r
             final AgentBase collector = gatheringEvent.getCollector();\r
             final String fieldNumber = fieldUnit.getFieldNumber();\r
-            dto.setCollection(((collector!=null?collector:"") + " " + (fieldNumber!=null?fieldNumber:"")).trim());\r
+            fieldUnitDTO.setCollection(((collector!=null?collector:"") + " " + (fieldNumber!=null?fieldNumber:"")).trim());\r
             //Date\r
             final Partial gatheringDate = gatheringEvent.getGatheringDate();\r
-            dto.setDate(gatheringDate!=null?gatheringDate.toString():"");\r
+            fieldUnitDTO.setDate(gatheringDate!=null?gatheringDate.toString():"");\r
         }\r
 \r
         //Taxon Name\r
-        dto.setTaxonName(associatedTaxon.getName().getFullTitleCache());\r
+        fieldUnitDTO.setTaxonName(associatedTaxon.getName().getFullTitleCache());\r
 \r
 \r
-        Collection<DerivedUnit> derivedUnits = new ArrayList<DerivedUnit>();\r
-        getDerivedUnitsFor(fieldUnit, derivedUnits);\r
-\r
         //Herbaria map\r
         Map<eu.etaxonomy.cdm.model.occurrence.Collection, Integer> collectionToCountMap = new HashMap<eu.etaxonomy.cdm.model.occurrence.Collection, Integer>();\r
         //List of accession numbers for citation\r
         List<String> preservedSpecimenAccessionNumbers = new ArrayList<String>();\r
 \r
-        //iterate over sub derivates\r
-        for (DerivedUnit derivedUnit : derivedUnits) {\r
+        //assemble preserved specimen DTOs\r
+        Set<DerivationEvent> derivationEvents = fieldUnit.getDerivationEvents();\r
+        for (DerivationEvent derivationEvent : derivationEvents) {\r
+            Set<DerivedUnit> derivatives = derivationEvent.getDerivatives();\r
+            for (DerivedUnit derivedUnit : derivatives) {\r
+                if(derivedUnit.getRecordBasis().equals(SpecimenOrObservationType.PreservedSpecimen)){\r
+                    PreservedSpecimenDTO preservedSpecimenDTO = assemblePreservedSpecimenDTO(derivedUnit, fieldUnitDTO);\r
+                    fieldUnitDTO.addPreservedSpecimenDTO(preservedSpecimenDTO);\r
+                    fieldUnitDTO.setHasCharacterData(preservedSpecimenDTO.isHasCharacterData());\r
+                    fieldUnitDTO.setHasDetailImage(preservedSpecimenDTO.isHasDetailImage());\r
+                    fieldUnitDTO.setHasDna(preservedSpecimenDTO.isHasDna());\r
+                    fieldUnitDTO.setHasSpecimenScan(preservedSpecimenDTO.isHasSpecimenScan());\r
+                }\r
+            }\r
+        }\r
+        //assemble derivate data DTO\r
+        assembleDerivateDataDTO(fieldUnitDTO, fieldUnit);\r
+\r
+        final String separator = ", ";\r
+        //assemble citation\r
+        String citation = "";\r
+        citation += !fieldUnitDTO.getCountry().isEmpty()?fieldUnitDTO.getCountry()+separator:"";\r
+        if(fieldUnit.getGatheringEvent()!=null){\r
+            if(fieldUnit.getGatheringEvent().getLocality()!=null){\r
+                citation += fieldUnit.getGatheringEvent().getLocality().getText();\r
+                citation += separator;\r
+            }\r
+            if(fieldUnit.getGatheringEvent().getExactLocation()!=null\r
+                    && fieldUnit.getGatheringEvent().getExactLocation().getLatitude()!=null\r
+                    && fieldUnit.getGatheringEvent().getExactLocation().getLongitude()!=null){\r
+                citation += fieldUnit.getGatheringEvent().getExactLocation().getLatitude().toString();\r
+                citation += separator;\r
+                citation += fieldUnit.getGatheringEvent().getExactLocation().getLongitude().toString();\r
+                citation += separator;\r
+            }\r
+        }\r
+        citation += !fieldUnitDTO.getCollection().isEmpty()?fieldUnitDTO.getCollection():"";\r
+        if(!preservedSpecimenAccessionNumbers.isEmpty()){\r
+            citation += " (";\r
+            for(String accessionNumber:preservedSpecimenAccessionNumbers){\r
+                if(!accessionNumber.isEmpty()){\r
+                    citation += accessionNumber+separator;\r
+                }\r
+            }\r
+            citation = removeTail(citation, separator);\r
+            citation += ")";\r
+        }\r
+        citation = removeTail(citation, separator);\r
+        fieldUnitDTO.setCitation(citation);\r
+\r
+        //assemble herbaria string\r
+        String herbariaString = "";\r
+        for(Entry<eu.etaxonomy.cdm.model.occurrence.Collection, Integer> e:collectionToCountMap.entrySet()){\r
+            eu.etaxonomy.cdm.model.occurrence.Collection collection = e.getKey();\r
+            if(collection.getCode()!=null){\r
+                herbariaString += collection.getCode();\r
+            }\r
+            if(e.getValue()>1){\r
+                herbariaString += "("+e.getValue()+")";\r
+            }\r
+            herbariaString += separator;\r
+        }\r
+        herbariaString = removeTail(herbariaString, separator);\r
+        fieldUnitDTO.setHerbarium(herbariaString);\r
+\r
+        return fieldUnitDTO;\r
+    }\r
+\r
+\r
+    @Override\r
+    public PreservedSpecimenDTO assemblePreservedSpecimenDTO(DerivedUnit derivedUnit){\r
+        return assemblePreservedSpecimenDTO(derivedUnit, null);\r
+    }\r
+\r
+    public PreservedSpecimenDTO assemblePreservedSpecimenDTO(DerivedUnit derivedUnit, FieldUnitDTO hierarchyDTO){\r
+        PreservedSpecimenDTO preservedSpecimenDTO = new PreservedSpecimenDTO();\r
+        preservedSpecimenDTO.setAccessionNumber(derivedUnit.getAccessionNumber());\r
+\r
+        //character state data\r
+        Collection<DescriptionElementBase> characterDataForSpecimen = getCharacterDataForSpecimen(derivedUnit);\r
+        if(!characterDataForSpecimen.isEmpty()){\r
+            if(hierarchyDTO!=null){\r
+                hierarchyDTO.setHasCharacterData(true);\r
+            }\r
+        }\r
+        for (DescriptionElementBase descriptionElementBase : characterDataForSpecimen) {\r
+            String character = descriptionElementBase.getFeature().getLabel();\r
+            ArrayList<Language> languages = new ArrayList<Language>(Collections.singleton(Language.DEFAULT()));\r
+            if(descriptionElementBase instanceof QuantitativeData){\r
+                QuantitativeData quantitativeData = (QuantitativeData)descriptionElementBase;\r
+                DefaultQuantitativeDescriptionBuilder builder = new DefaultQuantitativeDescriptionBuilder();\r
+                String state = builder.build(quantitativeData, languages).getText(Language.DEFAULT());\r
+                preservedSpecimenDTO.addCharacterData(character, state);\r
+            }\r
+            else if(descriptionElementBase instanceof CategoricalData){\r
+                CategoricalData categoricalData = (CategoricalData)descriptionElementBase;\r
+                DefaultCategoricalDescriptionBuilder builder = new DefaultCategoricalDescriptionBuilder();\r
+                String state = builder.build(categoricalData, languages).getText(Language.DEFAULT());\r
+                preservedSpecimenDTO.addCharacterData(character, state);\r
+            }\r
+        }\r
+        //check if derived unit is a type\r
+        Collection<SpecimenTypeDesignation> specimenTypeDesignations = listTypeDesignations(derivedUnit, null, null, null, null);\r
+        for (SpecimenTypeDesignation specimenTypeDesignation : specimenTypeDesignations) {\r
+            if(hierarchyDTO!=null){\r
+                hierarchyDTO.setHasType(true);\r
+            }\r
+            preservedSpecimenDTO.addType(specimenTypeDesignation.getTypeStatus().getLabel());\r
+        }\r
+        //assemble sub derivates\r
+        preservedSpecimenDTO.setDerivateDataDTO(assembleDerivateDataDTO(preservedSpecimenDTO, derivedUnit));\r
+        return preservedSpecimenDTO;\r
+    }\r
+\r
+    /**\r
+     * @param derivedUnit\r
+     * @param derivateDataDTO\r
+     * @return\r
+     */\r
+    private DerivateDataDTO assembleDerivateDataDTO(DerivateDTO derivateDTO, SpecimenOrObservationBase<?> specimenOrObservation) {\r
+        DerivateDataDTO derivateDataDTO = new DerivateDataDTO();\r
+        Collection<DerivedUnit> childDerivates = getDerivedUnitsFor(specimenOrObservation);\r
+        for (DerivedUnit childDerivate : childDerivates) {\r
             //current accession number\r
-            String currentAccessionNumber = derivedUnit.getAccessionNumber()!=null?derivedUnit.getAccessionNumber():"";\r
+            String currentAccessionNumber = childDerivate.getAccessionNumber()!=null?childDerivate.getAccessionNumber():"";\r
             //current herbarium\r
             String currentHerbarium = "";\r
-            eu.etaxonomy.cdm.model.occurrence.Collection collection = derivedUnit.getCollection();\r
+            eu.etaxonomy.cdm.model.occurrence.Collection collection = childDerivate.getCollection();\r
             if(collection!=null){\r
                 currentHerbarium = collection.getCode()!=null?collection.getCode():"";\r
-                //count herbaria\r
-                Integer count = collectionToCountMap.get(collection);\r
-                if(count==null){\r
-                    count = 1;\r
-                }\r
-                else{\r
-                    count++;\r
-                }\r
-                collectionToCountMap.put(collection, count);\r
-            }\r
-            //check if derived unit is a type\r
-            if(typeSpecimenUUIDtoTypeDesignationStatus.keySet().contains(derivedUnit.getUuid())){\r
-                dto.setHasType(true);\r
-                TypeDesignationStatusBase typeDesignationStatus = typeSpecimenUUIDtoTypeDesignationStatus.get(derivedUnit.getUuid());\r
-                String typeStatus = typeDesignationStatus.getLabel();\r
-                dto.addTypes(typeStatus, currentAccessionNumber);\r
             }\r
             //assemble molecular data\r
             //pattern: DNAMarker [contig1, primer1_1, primer1_2, ...][contig2, primer2_1, ...]...\r
-            if(derivedUnit.isInstanceOf(DnaSample.class)){\r
-                if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.TissueSample){\r
+            if(childDerivate.isInstanceOf(DnaSample.class)){\r
+                if(childDerivate.getRecordBasis()==SpecimenOrObservationType.TissueSample){\r
                     //TODO implement TissueSample assembly for web service\r
                 }\r
-                if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.DnaSample){\r
+                if(childDerivate.getRecordBasis()==SpecimenOrObservationType.DnaSample){\r
 \r
-                    DnaSample dna = HibernateProxyHelper.deproxy(derivedUnit, DnaSample.class);\r
+                    DnaSample dna = HibernateProxyHelper.deproxy(childDerivate, DnaSample.class);\r
                     if(!dna.getSequences().isEmpty()){\r
-                        dto.setHasDna(true);\r
+                        derivateDTO.setHasDna(true);\r
                     }\r
                     for(Sequence sequence:dna.getSequences()){\r
                         URI boldUri = null;\r
@@ -432,7 +527,7 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase<SpecimenOrObs
                             logger.error("Could not create BOLD URI", e1);\r
                         }\r
                         final DefinedTerm dnaMarker = sequence.getDnaMarker();\r
-                        MolecularData molecularData = dto.addProviderLink(boldUri!=null?boldUri:null,dnaMarker!=null?dnaMarker.getLabel():"[no marker]");\r
+                        MolecularData molecularData = derivateDataDTO.addProviderLink(boldUri!=null?boldUri:null,dnaMarker!=null?dnaMarker.getLabel():"[no marker]");\r
 \r
                         //contig file FIXME show primer although contig not present?\r
                         if(sequence.getContigFile()!=null){\r
@@ -454,84 +549,30 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase<SpecimenOrObs
                 }\r
             }\r
             //assemble media data\r
-            else if(derivedUnit.isInstanceOf(MediaSpecimen.class)){\r
+            else if(childDerivate.isInstanceOf(MediaSpecimen.class)){\r
 \r
-                MediaSpecimen media = HibernateProxyHelper.deproxy(derivedUnit, MediaSpecimen.class);\r
+                MediaSpecimen media = HibernateProxyHelper.deproxy(childDerivate, MediaSpecimen.class);\r
                 String mediaUriString = getMediaUriString(media);\r
                 if(media.getKindOfUnit()!=null){\r
                     //specimen scan\r
                     if(media.getKindOfUnit().getUuid().equals(UUID.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"))){\r
-                        dto.setHasSpecimenScan(true);\r
-                            final String imageLinkText = currentHerbarium+" "+currentAccessionNumber;\r
-                            dto.addSpecimenScan(mediaUriString==null?"":mediaUriString, !imageLinkText.equals(" ")?imageLinkText:"[no accession]");\r
+                        derivateDTO.setHasSpecimenScan(true);\r
+                        final String imageLinkText = currentHerbarium+" "+currentAccessionNumber;\r
+                        derivateDataDTO.addSpecimenScan(mediaUriString==null?"":mediaUriString, !imageLinkText.equals(" ")?imageLinkText:"[no accession]");\r
                     }\r
                     //detail image\r
                     else if(media.getKindOfUnit().getUuid().equals(UUID.fromString("31eb8d02-bf5d-437c-bcc6-87a626445f34"))){\r
-                        dto.setHasDetailImage(true);\r
+                        derivateDTO.setHasDetailImage(true);\r
                         String motif = "";\r
                         if(media.getMediaSpecimen()!=null && media.getMediaSpecimen().getTitle()!=null){\r
                             motif = media.getMediaSpecimen().getTitle().getText();\r
                         }\r
-                        dto.addDetailImage(mediaUriString==null?"":mediaUriString, motif!=null?motif:"[no motif]");\r
+                        derivateDataDTO.addDetailImage(mediaUriString==null?"":mediaUriString, motif!=null?motif:"[no motif]");\r
                     }\r
                 }\r
             }\r
-            //assemble preserved specimen data\r
-            else if(derivedUnit.getRecordBasis()==SpecimenOrObservationType.PreservedSpecimen){\r
-                if(!currentAccessionNumber.isEmpty()){\r
-                    preservedSpecimenAccessionNumbers.add(currentAccessionNumber);\r
-                }\r
-            }\r
-        }\r
-\r
-        final String separator = ", ";\r
-        //assemble citation\r
-        String citation = "";\r
-        citation += !dto.getCountry().isEmpty()?dto.getCountry()+separator:"";\r
-        if(fieldUnit.getGatheringEvent()!=null){\r
-            if(fieldUnit.getGatheringEvent().getLocality()!=null){\r
-                citation += fieldUnit.getGatheringEvent().getLocality().getText();\r
-                citation += separator;\r
-            }\r
-            if(fieldUnit.getGatheringEvent().getExactLocation()!=null\r
-                    && fieldUnit.getGatheringEvent().getExactLocation().getLatitude()!=null\r
-                    && fieldUnit.getGatheringEvent().getExactLocation().getLongitude()!=null){\r
-                citation += fieldUnit.getGatheringEvent().getExactLocation().getLatitude().toString();\r
-                citation += separator;\r
-                citation += fieldUnit.getGatheringEvent().getExactLocation().getLongitude().toString();\r
-                citation += separator;\r
-            }\r
-        }\r
-        citation += !dto.getCollection().isEmpty()?dto.getCollection():"";\r
-        if(!preservedSpecimenAccessionNumbers.isEmpty()){\r
-            citation += " (";\r
-            for(String accessionNumber:preservedSpecimenAccessionNumbers){\r
-                if(!accessionNumber.isEmpty()){\r
-                    citation += accessionNumber+separator;\r
-                }\r
-            }\r
-            citation = removeTail(citation, separator);\r
-            citation += ")";\r
         }\r
-        citation = removeTail(citation, separator);\r
-        dto.setCitation(citation);\r
-\r
-        //assemble herbaria string\r
-        String herbariaString = "";\r
-        for(Entry<eu.etaxonomy.cdm.model.occurrence.Collection, Integer> e:collectionToCountMap.entrySet()){\r
-            eu.etaxonomy.cdm.model.occurrence.Collection collection = e.getKey();\r
-            if(collection.getCode()!=null){\r
-                herbariaString += collection.getCode();\r
-            }\r
-            if(e.getValue()>1){\r
-                herbariaString += "("+e.getValue()+")";\r
-            }\r
-            herbariaString += separator;\r
-        }\r
-        herbariaString = removeTail(herbariaString, separator);\r
-        dto.setHerbarium(herbariaString);\r
-\r
-        return dto;\r
+        return derivateDataDTO;\r
     }\r
 \r
 \r
@@ -562,13 +603,15 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase<SpecimenOrObs
         return mediaUri;\r
     }\r
 \r
-    private void getDerivedUnitsFor(SpecimenOrObservationBase<?> specimen, Collection<DerivedUnit> derivedUnits){\r
+    private Collection<DerivedUnit> getDerivedUnitsFor(SpecimenOrObservationBase<?> specimen){\r
+        Collection<DerivedUnit> derivedUnits = new ArrayList<DerivedUnit>();\r
         for(DerivationEvent derivationEvent:specimen.getDerivationEvents()){\r
             for(DerivedUnit derivative:derivationEvent.getDerivatives()){\r
                 derivedUnits.add(derivative);\r
-                getDerivedUnitsFor(derivative, derivedUnits);\r
+                derivedUnits.addAll(getDerivedUnitsFor(derivative));\r
             }\r
         }\r
+        return derivedUnits;\r
     }\r
 \r
 \r
@@ -1167,4 +1210,42 @@ public class OccurrenceServiceImpl extends IdentifiableServiceBase<SpecimenOrObs
         return dao.listDescriptionsWithDescriptionSpecimen(specimen, limit, start, orderHints, propertyPaths);\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getStatesForSpecimen(eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase)\r
+     */\r
+    @Override\r
+    public Collection<DescriptionElementBase> getCharacterDataForSpecimen(SpecimenOrObservationBase<?> specimen) {\r
+        Collection<DescriptionElementBase> states = new ArrayList<DescriptionElementBase>();\r
+        if(specimen!=null){\r
+            Set<DescriptionBase> descriptions = specimen.getDescriptions();\r
+            for (DescriptionBase<?> descriptionBase : descriptions) {\r
+                if(descriptionBase.isInstanceOf(SpecimenDescription.class)){\r
+                    SpecimenDescription specimenDescription = HibernateProxyHelper.deproxy(descriptionBase, SpecimenDescription.class);\r
+                    Set<DescriptionElementBase> elements = specimenDescription.getElements();\r
+                    for (DescriptionElementBase descriptionElementBase : elements) {\r
+                        if(descriptionElementBase.getFeature().isSupportsCategoricalData()\r
+                                ||descriptionElementBase.getFeature().isSupportsQuantitativeData()){\r
+                            states.add(descriptionElementBase);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return states;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.api.service.IOccurrenceService#getStatesForSpecimen(java.util.UUID)\r
+     */\r
+    @Override\r
+    public Collection<DescriptionElementBase> getCharacterDataForSpecimen(UUID specimenUuid) {\r
+        SpecimenOrObservationBase<?> specimen = load(specimenUuid);\r
+        if(specimen!=null){\r
+            return getCharacterDataForSpecimen(specimen);\r
+        }\r
+        else{\r
+            throw new DataRetrievalFailureException("Specimen with the given uuid not found in the data base");\r
+        }\r
+    }\r
+\r
 }\r
diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateDTO.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateDTO.java
new file mode 100644 (file)
index 0000000..acd478d
--- /dev/null
@@ -0,0 +1,116 @@
+// $Id$
+/**
+* Copyright (C) 2015 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.api.service.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hibernate.envers.tools.Pair;
+
+/**
+ * @author pplitzner
+ * @date Mar 27, 2015
+ *
+ */
+public abstract class DerivateDTO {
+
+    private boolean hasDna;
+    private boolean hasDetailImage;
+    private boolean hasCharacterData;
+    private List<Pair<String, String>> characterData;
+    private DerivateDataDTO derivateDataDTO;
+    private boolean hasSpecimenScan;
+
+    /**
+     * @return the derivateDataDTO
+     */
+    public DerivateDataDTO getDerivateDataDTO() {
+        return derivateDataDTO;
+    }
+
+    /**
+     * @param derivateDataDTO the derivateDataDTO to set
+     */
+    public void setDerivateDataDTO(DerivateDataDTO derivateDataDTO) {
+        this.derivateDataDTO = derivateDataDTO;
+    }
+
+    /**
+     * @return the characterData
+     */
+    public List<Pair<String, String>> getCharacterData() {
+        return characterData;
+    }
+
+    public void addCharacterData(String character, String state){
+      if(characterData==null){
+          characterData = new ArrayList<Pair<String,String>>();
+      }
+      characterData.add(new Pair<String, String>(character, state));
+    }
+
+    /**
+     * @return the hasDna
+     */
+    public boolean isHasDna() {
+        return hasDna;
+    }
+
+    /**
+     * @param hasDna the hasDna to set
+     */
+    public void setHasDna(boolean hasDna) {
+        this.hasDna = hasDna;
+    }
+
+    /**
+     * @return the hasDetailImage
+     */
+    public boolean isHasDetailImage() {
+        return hasDetailImage;
+    }
+
+    /**
+     * @param hasDetailImage the hasDetailImage to set
+     */
+    public void setHasDetailImage(boolean hasDetailImage) {
+        this.hasDetailImage = hasDetailImage;
+    }
+
+    /**
+     * @return the hasCharacterData
+     */
+    public boolean isHasCharacterData() {
+        return hasCharacterData;
+    }
+
+    /**
+     * @param hasCharacterData the hasCharacterData to set
+     */
+    public void setHasCharacterData(boolean hasCharacterData) {
+        this.hasCharacterData = hasCharacterData;
+    }
+
+    /**
+     * @return the hasSpecimenScan
+     */
+    public boolean isHasSpecimenScan() {
+        return hasSpecimenScan;
+    }
+
+    /**
+     * @param hasSpecimenScan the hasSpecimenScan to set
+     */
+    public void setHasSpecimenScan(boolean hasSpecimenScan) {
+        this.hasSpecimenScan = hasSpecimenScan;
+    }
+
+
+}
similarity index 50%
rename from cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateHierarchyDTO.java
rename to cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/DerivateDataDTO.java
index 37aca87820d4bb150cbdad23493d813ab0b04569..f007c8be794d7be2c6d85c9f261eb2cb8fa3698c 100644 (file)
@@ -1,37 +1,32 @@
+// $Id$
+/**
+* Copyright (C) 2015 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
 package eu.etaxonomy.cdm.api.service.dto;
 
 import java.net.URI;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.hibernate.envers.tools.Pair;
 
-public class DerivateHierarchyDTO {
+/**
+ * @author pplitzner
+ * @date Mar 26, 2015
+ *
+ */
+public class DerivateDataDTO {
 
-       //Filter Flags
-       private boolean hasDna;
-       private boolean hasDetailImage;
+    private List<Pair<String, String>> specimenScans;
+    private List<MolecularData> molecularDataList;
+    private List<Pair<String, String>> detailImages;
 
-       //Row Attributes
-       private String country;
-       private String collection;
-       private String date;
-       private String herbarium;
-       private boolean hasType;
-       private boolean hasSpecimenScan;
-
-       //Detail pop-down
-       private String taxonName;
-       private String protologue;
-       private String citation;
-       private Map<String, List<String>> types;
-       private List<Pair<String, String>> specimenScans;
-       private List<MolecularData> molecularDataList;
-       private List<Pair<String, String>> detailImages;
-
-       /**
+    /**
      * @return the molecularData
      */
     public List<MolecularData> getMolecularDataList() {
@@ -40,176 +35,13 @@ public class DerivateHierarchyDTO {
 
     public MolecularData addProviderLink(URI uri, String linkText) {
         if(this.molecularDataList==null){
-            molecularDataList = new ArrayList<DerivateHierarchyDTO.MolecularData>();
+            molecularDataList = new ArrayList<MolecularData>();
         }
         MolecularData molecularData = new MolecularData(new Link(uri, linkText));
         this.molecularDataList.add(molecularData);
         return molecularData;
     }
 
-    /**
-     * @return the hasDna
-     */
-    public boolean isHasDna() {
-        return hasDna;
-    }
-    /**
-     * @param hasDna the hasDna to set
-     */
-    public void setHasDna(boolean hasDna) {
-        this.hasDna = hasDna;
-    }
-    /**
-     * @return the hasDetailImage
-     */
-    public boolean isHasDetailImage() {
-        return hasDetailImage;
-    }
-    /**
-     * @param hasDetailImage the hasDetailImage to set
-     */
-    public void setHasDetailImage(boolean hasDetailImage) {
-        this.hasDetailImage = hasDetailImage;
-    }
-    /**
-     * @return the country
-     */
-    public String getCountry() {
-        return country;
-    }
-    /**
-     * @param country the country to set
-     */
-    public void setCountry(String country) {
-        this.country = country;
-    }
-    /**
-     * @return the collection
-     */
-    public String getCollection() {
-        return collection;
-    }
-    /**
-     * @param collection the collection to set
-     */
-    public void setCollection(String collection) {
-        this.collection = collection;
-    }
-    /**
-     * @return the date
-     */
-    public String getDate() {
-        return date;
-    }
-    /**
-     * @param date the date to set
-     */
-    public void setDate(String date) {
-        this.date = date;
-    }
-    /**
-     * @return the herbarium
-     */
-    public String getHerbarium() {
-        return herbarium;
-    }
-    /**
-     * @param herbarium the herbarium to set
-     */
-    public void setHerbarium(String herbarium) {
-        this.herbarium = herbarium;
-    }
-    /**
-     * @return the hasType
-     */
-    public boolean isHasType() {
-        return hasType;
-    }
-    /**
-     * @param hasType the hasType to set
-     */
-    public void setHasType(boolean hasType) {
-        this.hasType = hasType;
-    }
-    /**
-     * @return the hasSpecimenScan
-     */
-    public boolean isHasSpecimenScan() {
-        return hasSpecimenScan;
-    }
-    /**
-     * @param hasSpecimenScan the hasSpecimenScan to set
-     */
-    public void setHasSpecimenScan(boolean hasSpecimenScan) {
-        this.hasSpecimenScan = hasSpecimenScan;
-    }
-    /**
-     * @return the taxonName
-     */
-    public String getTaxonName() {
-        return taxonName;
-    }
-    /**
-     * @param taxonName the taxonName to set
-     */
-    public void setTaxonName(String taxonName) {
-        this.taxonName = taxonName;
-    }
-    /**
-     * @return the protologue
-     */
-    public String getProtologue() {
-        return protologue;
-    }
-    /**
-     * @param protologue the protologue to set
-     */
-    public void setProtologue(String protologue) {
-        this.protologue = protologue;
-    }
-    /**
-     * @return the citation
-     */
-    public String getCitation() {
-        return citation;
-    }
-    /**
-     * @param citation the citation to set
-     */
-    public void setCitation(String citation) {
-        this.citation = citation;
-    }
-
-    /**
-     * @param types the types to set
-     */
-    public void setTypes(Map<String, List<String>> types) {
-        this.types = types;
-    }
-    /**
-     * @return the types
-     */
-    public Map<String, List<String>> getTypes() {
-        return types;
-    }
-    public void addTypes(String typeStatus, String accessionNumber){
-        if(types==null){
-            types = new HashMap<String, List<String>>();
-        }
-        List<String> list = types.get(typeStatus);
-        if(list==null){
-            list = new ArrayList<String>();
-        }
-        list.add(accessionNumber);
-        types.put(typeStatus, list);
-    }
-
-    /**
-     * @param specimenScans the specimenScans to set
-     */
-    public void setSpecimenScans(List<Pair<String, String>> specimenScans) {
-        this.specimenScans = specimenScans;
-    }
     /**
      * @return the specimenScans
      */
@@ -230,12 +62,6 @@ public class DerivateHierarchyDTO {
     public List<Pair<String, String>> getDetailImages() {
         return detailImages;
     }
-    /**
-     * @param detailImages the detailImages to set
-     */
-    public void setDetailImages(List<Pair<String, String>> detailImages) {
-        this.detailImages = detailImages;
-    }
 
     public void addDetailImage(String uri, String motif){
         if(detailImages==null){
@@ -255,7 +81,7 @@ public class DerivateHierarchyDTO {
 
         public ContigFile addContigFile(URI uri, String linkText){
             if(contigFiles==null){
-                contigFiles = new ArrayList<DerivateHierarchyDTO.ContigFile>();
+                contigFiles = new ArrayList<ContigFile>();
             }
             ContigFile contigFile = new ContigFile(new Link(uri, linkText));
             contigFiles.add(contigFile);
@@ -282,7 +108,7 @@ public class DerivateHierarchyDTO {
 
         public void addPrimerLink(URI uri, String linkText){
             if(primerLinks==null){
-                primerLinks = new ArrayList<DerivateHierarchyDTO.Link>();
+                primerLinks = new ArrayList<Link>();
             }
             primerLinks.add(new Link(uri, linkText));
         }
@@ -374,4 +200,5 @@ public class DerivateHierarchyDTO {
         }
     }
 
+
 }
diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/FieldUnitDTO.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/FieldUnitDTO.java
new file mode 100644 (file)
index 0000000..557591e
--- /dev/null
@@ -0,0 +1,133 @@
+package eu.etaxonomy.cdm.api.service.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class FieldUnitDTO extends DerivateDTO{
+
+       //Row Attributes
+       private String country;
+       private String collection;
+       private String date;
+       private String herbarium;
+       private boolean hasType;
+       //Detail pop-down
+       private String taxonName;
+       private String citation;
+       private String protologue;
+
+       private List<PreservedSpecimenDTO> preservedSpecimenDTOs;
+
+    /**
+     * @return the country
+     */
+    public String getCountry() {
+        return country;
+    }
+    /**
+     * @param country the country to set
+     */
+    public void setCountry(String country) {
+        this.country = country;
+    }
+    /**
+     * @return the collection
+     */
+    public String getCollection() {
+        return collection;
+    }
+    /**
+     * @param collection the collection to set
+     */
+    public void setCollection(String collection) {
+        this.collection = collection;
+    }
+    /**
+     * @return the date
+     */
+    public String getDate() {
+        return date;
+    }
+    /**
+     * @param date the date to set
+     */
+    public void setDate(String date) {
+        this.date = date;
+    }
+    /**
+     * @return the herbarium
+     */
+    public String getHerbarium() {
+        return herbarium;
+    }
+    /**
+     * @param herbarium the herbarium to set
+     */
+    public void setHerbarium(String herbarium) {
+        this.herbarium = herbarium;
+    }
+    /**
+     * @return the hasType
+     */
+    public boolean isHasType() {
+        return hasType;
+    }
+    /**
+     * @param hasType the hasType to set
+     */
+    public void setHasType(boolean hasType) {
+        this.hasType = hasType;
+    }
+    /**
+     * @return the taxonName
+     */
+    public String getTaxonName() {
+        return taxonName;
+    }
+    /**
+     * @param taxonName the taxonName to set
+     */
+    public void setTaxonName(String taxonName) {
+        this.taxonName = taxonName;
+    }
+    /**
+     * @return the protologue
+     */
+    public String getProtologue() {
+        return protologue;
+    }
+    /**
+     * @param protologue the protologue to set
+     */
+    public void setProtologue(String protologue) {
+        this.protologue = protologue;
+    }
+    /**
+     * @return the citation
+     */
+    public String getCitation() {
+        return citation;
+    }
+    /**
+     * @param citation the citation to set
+     */
+    public void setCitation(String citation) {
+        this.citation = citation;
+    }
+
+    /**
+     * @return the derivateDTOs
+     */
+    public List<PreservedSpecimenDTO> getPreservedSpecimenDTOs() {
+        return preservedSpecimenDTOs;
+    }
+
+    public void addPreservedSpecimenDTO(PreservedSpecimenDTO preservedSpecimenDTO){
+        if(preservedSpecimenDTOs==null){
+            preservedSpecimenDTOs = new ArrayList<PreservedSpecimenDTO>();
+        }
+        preservedSpecimenDTOs.add(preservedSpecimenDTO);
+    }
+
+}
diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/PreservedSpecimenDTO.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/dto/PreservedSpecimenDTO.java
new file mode 100644 (file)
index 0000000..bfc5389
--- /dev/null
@@ -0,0 +1,51 @@
+// $Id$
+/**
+* Copyright (C) 2015 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.api.service.dto;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author pplitzner
+ * @date Mar 26, 2015
+ *
+ */
+public class PreservedSpecimenDTO extends DerivateDTO{
+
+    private String accessionNumber;
+    private List<String> types;
+
+    /**
+     * @return the accessionNumber
+     */
+    public String getAccessionNumber() {
+        return accessionNumber;
+    }
+    /**
+     * @param accessionNumber the accessionNumber to set
+     */
+    public void setAccessionNumber(String accessionNumber) {
+        this.accessionNumber = accessionNumber;
+    }
+    /**
+     * @return the types
+     */
+    public List<String> getTypes() {
+        return types;
+    }
+    public void addType(String typeStatus){
+        if(types==null){
+            types = new ArrayList<String>();
+        }
+        types.add(typeStatus);
+    }
+
+}