tests for image galleries in derived unit facade and bugfix for test in DescriptionSe...
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / facade / DerivedUnitFacade.java
index 0e5142eee558041726ee544ea9abfb81cb38dbf1..5ab077055e5f2424aed942ea70b6143c8b55adde 100644 (file)
@@ -11,7 +11,6 @@ package eu.etaxonomy.cdm.api.facade;
 \r
 import java.beans.PropertyChangeEvent;\r
 import java.beans.PropertyChangeListener;\r
-import java.beans.PropertyChangeSupport;\r
 import java.text.ParseException;\r
 import java.util.ArrayList;\r
 import java.util.HashMap;\r
@@ -20,14 +19,13 @@ import java.util.List;
 import java.util.Map;\r
 import java.util.Set;\r
 \r
-import javax.mail.MethodNotSupportedException; //FIMXE use other execption class\r
 import javax.persistence.Transient;\r
 \r
-\r
 import org.apache.log4j.Logger;\r
 \r
 import eu.etaxonomy.cdm.api.service.IOccurrenceService;\r
 import eu.etaxonomy.cdm.model.agent.AgentBase;\r
+import eu.etaxonomy.cdm.model.agent.Person;\r
 import eu.etaxonomy.cdm.model.common.Annotation;\r
 import eu.etaxonomy.cdm.model.common.CdmBase;\r
 import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
@@ -54,7 +52,7 @@ import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
 import eu.etaxonomy.cdm.model.occurrence.PreservationMethod;\r
 import eu.etaxonomy.cdm.model.occurrence.Specimen;\r
 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;\r
-import eu.etaxonomy.cdm.model.reference.ReferenceBase;\r
+import eu.etaxonomy.cdm.model.reference.Reference;\r
 \r
 /**\r
  * This class is a facade to the eu.etaxonomy.cdm.model.occurrence package from\r
@@ -143,7 +141,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        /**\r
-        * Creates a derived unit facade for a given derived unit using the default configuation.\r
+        * Creates a derived unit facade for a given derived unit using the default configuration.\r
         * @param derivedUnit\r
         * @return\r
         * @throws DerivedUnitFacadeNotSupportedException\r
@@ -205,7 +203,7 @@ public class DerivedUnitFacade {
 //             String objectTypeExceptionText = "Specimen";\r
 //             SpecimenDescription imageGallery = getImageGalleryWithSupportTest(derivedUnit, objectTypeExceptionText, false);\r
 //             getImageTextDataWithSupportTest(imageGallery, objectTypeExceptionText);\r
-               this.derivedUnitMediaTextData = inititialzeTextDataWithSupportTest(Feature.IMAGE(), this.derivedUnit, false, true);\r
+               this.derivedUnitMediaTextData = inititializeTextDataWithSupportTest(Feature.IMAGE(), this.derivedUnit, false, true);\r
                \r
                //field observation\r
 //             objectTypeExceptionText = "Field observation";\r
@@ -358,6 +356,8 @@ public class DerivedUnitFacade {
         * Transforms the property paths in a way that the facade is handled just like an \r
         * ordinary CdmBase object.<BR>\r
         * E.g. a property path "collectinAreas" will be translated into gatheringEvent.collectingAreas\r
+        * \r
+        * Not needed (?) as the facade works with REST service property paths without using this method.\r
         * @param propertyPaths\r
         * @return\r
         */\r
@@ -425,6 +425,9 @@ public class DerivedUnitFacade {
         * \r
         */\r
        private void setCacheStrategy() {\r
+               if (derivedUnit == null){\r
+                       throw new NullPointerException("Facade's derviedUnit must not be null to set cache strategy");\r
+               }\r
                derivedUnit.setCacheStrategy(new DerivedUnitFacadeCacheStrategy());\r
        }\r
 \r
@@ -442,7 +445,7 @@ public class DerivedUnitFacade {
                if (fieldObject == null){\r
                        return null;\r
                }\r
-               return inititialzeTextDataWithSupportTest(feature, fieldObject, createIfNotExists, isImageGallery);\r
+               return inititializeTextDataWithSupportTest(feature, fieldObject, createIfNotExists, isImageGallery);\r
        }\r
 \r
 \r
@@ -454,7 +457,7 @@ public class DerivedUnitFacade {
         * @return\r
         * @throws DerivedUnitFacadeNotSupportedException\r
         */\r
-       private TextData inititialzeTextDataWithSupportTest(Feature feature, SpecimenOrObservationBase specimen, boolean createIfNotExists, \r
+       private TextData inititializeTextDataWithSupportTest(Feature feature, SpecimenOrObservationBase specimen, boolean createIfNotExists, \r
                                boolean isImageGallery) throws DerivedUnitFacadeNotSupportedException {\r
                if (feature == null ){\r
                        return null;\r
@@ -498,6 +501,36 @@ public class DerivedUnitFacade {
                        return textData;\r
                }\r
        }\r
+       \r
+\r
+       /**\r
+        * Tests if a given image gallery is supported by the derived unit facade.\r
+        * It returns the only text data attached to the given image gallery.\r
+        * If the given image gallery does not have text data attached, it is created and attached.\r
+        * @param imageGallery\r
+        * @return\r
+        * @throws DerivedUnitFacadeNotSupportedException\r
+        */\r
+       private TextData testImageGallery(SpecimenDescription imageGallery) throws DerivedUnitFacadeNotSupportedException {\r
+               if (imageGallery.isImageGallery() == false){\r
+                       throw new DerivedUnitFacadeNotSupportedException("Image gallery needs to have image gallery flag set");\r
+               }\r
+               if (imageGallery.getElements().size() > 1){\r
+                       throw new DerivedUnitFacadeNotSupportedException("Image gallery must not have more then one description element");\r
+               }\r
+               TextData textData;\r
+               if (imageGallery.getElements().size() == 0){\r
+                       textData = TextData.NewInstance(Feature.IMAGE());\r
+                       imageGallery.addElement(textData);\r
+               }else{\r
+                       if (! imageGallery.getElements().iterator().next().isInstanceOf(TextData.class)){\r
+                               throw new DerivedUnitFacadeNotSupportedException("Image gallery must only have TextData as element");\r
+                       }else{\r
+                               textData = CdmBase.deproxy(imageGallery.getElements().iterator().next(), TextData.class);\r
+                       }\r
+               }\r
+               return textData;\r
+       }\r
 \r
 //************************** METHODS ***************************************** \r
 \r
@@ -940,7 +973,7 @@ public class DerivedUnitFacade {
        }\r
        \r
        /**\r
-        * Returns a sexagesimal representation of the exact location (e.g. 12°59'N, 35°23E).\r
+        * Returns a sexagesimal representation of the exact location (e.g. 12°59'N, 35°23E).\r
         * If the exact location is <code>null</code> the empty string is returned.\r
         * @param includeEmptySeconds\r
         * @param includeReferenceSystem\r
@@ -982,6 +1015,10 @@ public class DerivedUnitFacade {
        public LanguageString getLocality(){\r
                return (hasGatheringEvent() ? getGatheringEvent(true).getLocality() : null);\r
        }\r
+       /**\r
+        * convienience method for {@link #getLocality()}.{@link LanguageString#getText() getText()}\r
+        * @return\r
+        */\r
        @Transient\r
        public String getLocalityText(){\r
                LanguageString locality = getLocality();\r
@@ -990,6 +1027,10 @@ public class DerivedUnitFacade {
                }\r
                return null;\r
        }\r
+       /**\r
+        * convienience method for {@link #getLocality()}.{@link LanguageString#getLanguage() getLanguage()}\r
+        * @return\r
+        */\r
        @Transient\r
        public Language getLocalityLanguage(){\r
                LanguageString locality = getLocality();\r
@@ -1037,8 +1078,8 @@ public class DerivedUnitFacade {
        public boolean hasGatheringEvent(){\r
                return (getGatheringEvent(false) != null);\r
        }\r
-       @Transient\r
-       public GatheringEvent getGatheringEvent() {\r
+       \r
+       public GatheringEvent innerGatheringEvent() {\r
                return getGatheringEvent(false);\r
        }\r
        \r
@@ -1076,6 +1117,11 @@ public class DerivedUnitFacade {
 //             LanguageString languageString = getEcologyAll().getPreferredLanguageString(languages);\r
 //             return languageString.getText();\r
 //     }\r
+       /**\r
+        * Returns a copy of the multilanguage text holding the ecology data.\r
+        * @see {@link TextData#getMultilanguageText()}\r
+        * @return\r
+        */\r
        @Transient\r
        public Map<Language, LanguageString> getEcologyAll(){\r
                if (ecology == null){\r
@@ -1108,7 +1154,7 @@ public class DerivedUnitFacade {
                if (ecologyText == null){\r
                        ecology.removeText(language);\r
                }else{\r
-                       ecology.putText(ecologyText, language);\r
+                       ecology.putText(language, ecologyText);\r
                }\r
        }\r
        public void removeEcology(Language language){\r
@@ -1141,6 +1187,11 @@ public class DerivedUnitFacade {
 //             LanguageString languageString = getPlantDescriptionAll().getPreferredLanguageString(languages);\r
 //             return languageString.getText();\r
 //     }\r
+       /**\r
+        * Returns a copy of the multilanguage text holding the description data.\r
+        * @see {@link TextData#getMultilanguageText()}\r
+        * @return\r
+        */\r
        @Transient\r
        public Map<Language, LanguageString> getPlantDescriptionAll(){\r
                if (plantDescription == null){\r
@@ -1172,7 +1223,7 @@ public class DerivedUnitFacade {
                if (plantDescriptionText == null){\r
                        plantDescription.removeText(language);\r
                }else{\r
-                       plantDescription.putText(plantDescriptionText, language);\r
+                       plantDescription.putText(language, plantDescriptionText);\r
                }\r
        }\r
        public void removePlantDescription(Language language){\r
@@ -1228,7 +1279,29 @@ public class DerivedUnitFacade {
                }\r
        }\r
        \r
+       public void setFieldObjectImageGallery(SpecimenDescription imageGallery) throws DerivedUnitFacadeNotSupportedException{\r
+               SpecimenDescription existingGallery = getFieldObjectImageGallery(false);\r
+               \r
+               //test attached specimens contain this.derivedUnit\r
+               SpecimenOrObservationBase<?> facadeFieldObservation = innerFieldObservation();\r
+               testSpecimenInImageGallery(imageGallery, facadeFieldObservation);\r
+               \r
+               if (existingGallery != null){\r
+                       if (existingGallery != imageGallery){\r
+                               throw new DerivedUnitFacadeNotSupportedException("DerivedUnitFacade does not allow more than one image gallery");\r
+                       }else{\r
+                               //do nothing\r
+                       }\r
+               }else {\r
+                       TextData textData = testImageGallery(imageGallery);\r
+                       this.fieldObjectMediaTextData = textData;\r
+               }\r
+       }\r
+\r
+       \r
        /**\r
+        * Returns the field object image gallery. If no such image gallery exists and\r
+        * createIfNotExists is true an new one is created. Otherwise null is returned.\r
         * @param createIfNotExists\r
         * @return\r
         */\r
@@ -1279,6 +1352,20 @@ public class DerivedUnitFacade {
                getFieldObservation(true).setFieldNumber(fieldNumber);\r
        }\r
 \r
+       //primary collector\r
+       @Transient\r
+       public Person getPrimaryCollector() {\r
+               if (! hasFieldObservation()){\r
+                       return null;\r
+               }else{\r
+                       return getFieldObservation(true).getPrimaryCollector();\r
+               }\r
+       }\r
+       public void setPrimaryCollector(Person primaryCollector) {\r
+               getFieldObservation(true).setPrimaryCollector(primaryCollector);\r
+       }\r
+       \r
+       \r
        \r
        //field notes\r
        @Transient\r
@@ -1331,8 +1418,7 @@ public class DerivedUnitFacade {
         * Returns the field observation as an object.\r
         * @return\r
         */\r
-       @Transient\r
-       public FieldObservation getFieldObservation(){\r
+       public FieldObservation innerFieldObservation(){\r
                return getFieldObservation(false);\r
        }\r
 \r
@@ -1408,7 +1494,7 @@ public class DerivedUnitFacade {
        public SpecimenDescription getDerivedUnitImageGallery(boolean createIfNotExists){\r
                TextData textData;\r
                try {\r
-                       textData = inititialzeTextDataWithSupportTest(Feature.IMAGE(), derivedUnit, createIfNotExists, true);\r
+                       textData = inititializeTextDataWithSupportTest(Feature.IMAGE(), derivedUnit, createIfNotExists, true);\r
                } catch (DerivedUnitFacadeNotSupportedException e) {\r
                        throw new IllegalStateException(notSupportMessage, e);\r
                }\r
@@ -1418,6 +1504,38 @@ public class DerivedUnitFacade {
                        return null;\r
                }\r
        }\r
+       public void setDerivedUnitImageGallery(SpecimenDescription imageGallery) throws DerivedUnitFacadeNotSupportedException{\r
+               SpecimenDescription existingGallery = getDerivedUnitImageGallery(false);\r
+               \r
+               //test attached specimens contain this.derivedUnit\r
+               SpecimenOrObservationBase facadeDerivedUnit = innerDerivedUnit();\r
+               testSpecimenInImageGallery(imageGallery, facadeDerivedUnit);\r
+               \r
+               if (existingGallery != null){\r
+                       if (existingGallery != imageGallery){\r
+                               throw new DerivedUnitFacadeNotSupportedException("DerivedUnitFacade does not allow more than one image gallery");\r
+                       }else{\r
+                               //do nothing\r
+                       }\r
+               }else {\r
+                       TextData textData = testImageGallery(imageGallery);\r
+                       this.derivedUnitMediaTextData = textData;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * @param imageGallery\r
+        * @throws DerivedUnitFacadeNotSupportedException\r
+        */\r
+       private void testSpecimenInImageGallery(SpecimenDescription imageGallery, SpecimenOrObservationBase specimen) throws DerivedUnitFacadeNotSupportedException {\r
+               Set<SpecimenOrObservationBase> imageGallerySpecimens = imageGallery.getDescribedSpecimenOrObservations();\r
+               if (imageGallerySpecimens.size() < 1){\r
+                       throw new DerivedUnitFacadeNotSupportedException("Image Gallery has no Specimen attached. Please attache according specimen or field observation.");\r
+               }\r
+               if (! imageGallerySpecimens.contains(specimen)){\r
+                       throw new DerivedUnitFacadeNotSupportedException("Image Gallery has not the facade's field object attached. Please add field object first to image gallery specimenOrObservation list.");\r
+               }\r
+       }\r
        \r
        /**\r
         * Returns the media for the specimen.<BR>\r
@@ -1463,7 +1581,7 @@ public class DerivedUnitFacade {
                return derivedUnit.getBarcode();\r
        }\r
        public void setBarcode(String barcode) {\r
-               derivedUnit.setCatalogNumber(barcode);\r
+               derivedUnit.setBarcode(barcode);\r
        }\r
 \r
        \r
@@ -1530,6 +1648,9 @@ public class DerivedUnitFacade {
                }\r
                return this.derivedUnit.getTitleCache();\r
        }\r
+       public boolean isProtectedTitleCache(){\r
+               return derivedUnit.isProtectedTitleCache();\r
+       }\r
        public void setTitleCache(String titleCache, boolean isProtected) {\r
                this.derivedUnit.setTitleCache(titleCache, isProtected);\r
        }\r
@@ -1539,8 +1660,7 @@ public class DerivedUnitFacade {
         * Returns the derived unit itself.\r
         * @return the derived unit\r
         */\r
-       @Transient\r
-       public DerivedUnitBase getDerivedUnit() {\r
+       public DerivedUnitBase innerDerivedUnit() {\r
                return this.derivedUnit;\r
        }\r
        \r
@@ -1559,13 +1679,28 @@ public class DerivedUnitFacade {
                return result;\r
        }\r
        @Transient\r
-       public String getExsiccatum() {\r
-               logger.warn("Exsiccatum method not yet supported. Needs model change");\r
-               return null;\r
+       public String getExsiccatum() throws MethodNotSupportedByDerivedUnitTypeException {\r
+               if (derivedUnit.isInstanceOf(Specimen.class)){\r
+                       return CdmBase.deproxy(derivedUnit, Specimen.class).getExsiccatum();\r
+               }else{\r
+                       if (this.config.isThrowExceptionForNonSpecimenPreservationMethodRequest()){\r
+                               throw new MethodNotSupportedByDerivedUnitTypeException("An exsiccatum is only available in derived units of type 'Specimen' or 'Fossil'");\r
+                       }else{\r
+                               return null;\r
+                       }\r
+               }\r
        }\r
        \r
-       public String setExsiccatum() throws MethodNotSupportedException{\r
-               throw new MethodNotSupportedException("Exsiccatum method not yet supported. Needs model change");\r
+       public void setExsiccatum(String exsiccatum) throws Exception{\r
+               if (derivedUnit.isInstanceOf(Specimen.class)){\r
+                       CdmBase.deproxy(derivedUnit, Specimen.class).setExsiccatum(exsiccatum);\r
+               }else{\r
+                       if (this.config.isThrowExceptionForNonSpecimenPreservationMethodRequest()){\r
+                               throw new MethodNotSupportedByDerivedUnitTypeException("An exsiccatum is only available in derived units of type 'Specimen' or 'Fossil'");\r
+                       }else{\r
+                               return;\r
+                       }\r
+               }\r
        }\r
        \r
        \r
@@ -1580,7 +1715,7 @@ public class DerivedUnitFacade {
         * @param originalNameString\r
         * @return\r
         */\r
-       public IdentifiableSource addSource(ReferenceBase reference, String microReference, String originalNameString){\r
+       public IdentifiableSource addSource(Reference reference, String microReference, String originalNameString){\r
                IdentifiableSource source = IdentifiableSource.NewInstance(reference, microReference);\r
                source.setOriginalNameString(originalNameString);\r
                derivedUnit.addSource(source);\r