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 51258f73d6255d0ccd43c33bb45f7b864f2f12e2..5ab077055e5f2424aed942ea70b6143c8b55adde 100644 (file)
@@ -9,18 +9,24 @@
 \r
 package eu.etaxonomy.cdm.api.facade;\r
 \r
+import java.beans.PropertyChangeEvent;\r
+import java.beans.PropertyChangeListener;\r
 import java.text.ParseException;\r
+import java.util.ArrayList;\r
 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
 \r
-import javax.mail.MethodNotSupportedException;\r
+import javax.persistence.Transient;\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
 import eu.etaxonomy.cdm.model.common.Language;\r
@@ -46,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
@@ -64,7 +70,6 @@ public class DerivedUnitFacade {
        \r
        private static final String notSupportMessage = "A specimen facade not supported exception has occurred at a place where this should not have happened. The developer should implement not support check properly during class initialization ";\r
        \r
-       \r
        /**\r
         * Enum that defines the class the "Specimen" belongs to.\r
         * Some methods of the facade are not available for certain classes\r
@@ -116,24 +121,41 @@ public class DerivedUnitFacade {
        private FieldObservation fieldObservation;\r
        \r
        private DerivedUnitBase derivedUnit;\r
-       private List<Media> specimenMedia;\r
-       private List<Media> fieldObservationMedia;\r
+\r
+       //media - the text data holding the media\r
+       private TextData derivedUnitMediaTextData;\r
+       private TextData fieldObjectMediaTextData;\r
+       \r
        \r
        private TextData ecology;\r
        private TextData plantDescription;\r
        \r
+       \r
+       /**\r
+        * Creates a derived unit facade for a new derived unit of type <code>type</code>.\r
+        * @param type\r
+        * @return\r
+        */\r
        public static DerivedUnitFacade NewInstance(DerivedUnitType type){\r
                return new DerivedUnitFacade(type);\r
        }\r
 \r
+       /**\r
+        * Creates a derived unit facade for a given derived unit using the default configuration.\r
+        * @param derivedUnit\r
+        * @return\r
+        * @throws DerivedUnitFacadeNotSupportedException\r
+        */\r
        public static DerivedUnitFacade NewInstance(DerivedUnitBase derivedUnit) throws DerivedUnitFacadeNotSupportedException{\r
-               return new DerivedUnitFacade(derivedUnit, null, DerivedUnitType.Specimen);\r
+               return new DerivedUnitFacade(derivedUnit, null);\r
        }\r
        \r
        public static DerivedUnitFacade NewInstance(DerivedUnitBase derivedUnit, DerivedUnitFacadeConfigurator config) throws DerivedUnitFacadeNotSupportedException{\r
-               return new DerivedUnitFacade(derivedUnit, config, DerivedUnitType.Specimen);\r
+               return new DerivedUnitFacade(derivedUnit, config);\r
        }\r
 \r
+\r
+       \r
 // ****************** CONSTRUCTOR ****************************************************\r
        \r
        private DerivedUnitFacade(DerivedUnitType type){\r
@@ -144,8 +166,7 @@ public class DerivedUnitFacade {
                setCacheStrategy();\r
        }\r
        \r
-       private DerivedUnitFacade(DerivedUnitBase derivedUnit, DerivedUnitFacadeConfigurator config, DerivedUnitType type) throws DerivedUnitFacadeNotSupportedException{\r
-               //this.type = type;  ??\r
+       private DerivedUnitFacade(DerivedUnitBase derivedUnit, DerivedUnitFacadeConfigurator config) throws DerivedUnitFacadeNotSupportedException{\r
                \r
                if (config == null){\r
                        config = DerivedUnitFacadeConfigurator.NewInstance();\r
@@ -167,23 +188,30 @@ public class DerivedUnitFacade {
                                //fieldObservation = FieldObservation.NewInstance();\r
                        }else if (fieldOriginals.size() == 1){\r
                                fieldObservation = fieldOriginals.iterator().next();\r
+                               //###fieldObservation = getInitializedFieldObservation(fieldObservation);\r
+                               fieldObservation.addPropertyChangeListener(getNewEventPropagationListener());\r
                        }else{\r
                                throw new IllegalStateException("Illegal state");\r
                        }       \r
                }\r
+               // #### derivedUnit = getInitializedDerivedUnit(derivedUnit);\r
 \r
                //test if unsupported\r
+               \r
+               //media\r
                //specimen\r
-               String objectTypeExceptionText = "Specimen";\r
-               SpecimenDescription imageGallery = getImageGalleryWithSupportTest(derivedUnit, objectTypeExceptionText, false);\r
-               getImageTextDataWithSupportTest(imageGallery, objectTypeExceptionText);\r
+//             String objectTypeExceptionText = "Specimen";\r
+//             SpecimenDescription imageGallery = getImageGalleryWithSupportTest(derivedUnit, objectTypeExceptionText, false);\r
+//             getImageTextDataWithSupportTest(imageGallery, objectTypeExceptionText);\r
+               this.derivedUnitMediaTextData = inititializeTextDataWithSupportTest(Feature.IMAGE(), this.derivedUnit, false, true);\r
                \r
                //field observation\r
-               objectTypeExceptionText = "Field observation";\r
-               imageGallery = getImageGalleryWithSupportTest(fieldObservation, objectTypeExceptionText, false);\r
-               getImageTextDataWithSupportTest(imageGallery, objectTypeExceptionText);\r
+//             objectTypeExceptionText = "Field observation";\r
+//             imageGallery = getImageGalleryWithSupportTest(fieldObservation, objectTypeExceptionText, false);\r
+//             getImageTextDataWithSupportTest(imageGallery, objectTypeExceptionText);\r
+               fieldObjectMediaTextData = initializeFieldObjectTextDataWithSupportTest(Feature.IMAGE(), false, true);\r
                \r
-               //direct media of derived unit\r
+               //handle derivedUnit.getMedia()\r
                if (derivedUnit.getMedia().size() > 0){\r
                        //TODO better changed model here to allow only one place for images\r
                        if (this.config.isMoveDerivedUnitMediaToGallery()){\r
@@ -197,7 +225,7 @@ public class DerivedUnitFacade {
                        }\r
                }\r
                \r
-               //direct media of field observation\r
+               //handle fieldObservation.getMedia()\r
                if (fieldObservation != null && fieldObservation.getMedia() != null && fieldObservation.getMedia().size() > 0){\r
                        //TODO better changed model here to allow only one place for images\r
                        if (this.config.isMoveFieldObjectMediaToGallery()){\r
@@ -212,24 +240,226 @@ public class DerivedUnitFacade {
                }\r
                \r
                //test if descriptions are supported\r
-               ecology = initializeFieldObjectTextDataWithSupportTest(Feature.ECOLOGY(), false);\r
-               plantDescription = initializeFieldObjectTextDataWithSupportTest(Feature.DESCRIPTION(), false);\r
+               ecology = initializeFieldObjectTextDataWithSupportTest(Feature.ECOLOGY(), false, false);\r
+               plantDescription = initializeFieldObjectTextDataWithSupportTest(Feature.DESCRIPTION(), false, false);\r
        }\r
        \r
 \r
+       private DerivedUnitBase getInitializedDerivedUnit(DerivedUnitBase derivedUnit) {\r
+               IOccurrenceService occurrenceService = this.config.getOccurrenceService();\r
+               if (occurrenceService == null){\r
+                       return derivedUnit;\r
+               }\r
+               List<String> propertyPaths = this.config.getPropertyPaths();\r
+               if (propertyPaths == null){\r
+                       return derivedUnit;\r
+               }\r
+               propertyPaths = getDerivedUnitPropertyPaths(propertyPaths);\r
+               DerivedUnitBase result = (DerivedUnitBase)occurrenceService.load(derivedUnit.getUuid(), propertyPaths);\r
+               return result;\r
+       }\r
+\r
+       /**\r
+        * Initializes the derived unit according to the configuartions property path.\r
+        * If the property path is <code>null</code> or no occurrence service is given the\r
+        * returned object is the same as the input parameter.\r
+        * @param fieldObservation2\r
+        * @return\r
+        */\r
+       private FieldObservation getInitializedFieldObservation(FieldObservation fieldObservation) {\r
+               IOccurrenceService occurrenceService = this.config.getOccurrenceService();\r
+               if (occurrenceService == null){\r
+                       return fieldObservation;\r
+               }\r
+               List<String> propertyPaths = this.config.getPropertyPaths();\r
+               if (propertyPaths == null){\r
+                       return fieldObservation;\r
+               }\r
+               propertyPaths = getFieldObjectPropertyPaths(propertyPaths);\r
+               FieldObservation result = (FieldObservation)occurrenceService.load(fieldObservation.getUuid(), propertyPaths);\r
+               return result;\r
+       }\r
+\r
+       /**\r
+        * 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
+        * @param propertyPaths\r
+        * @return\r
+        */\r
+       private List<String> getFieldObjectPropertyPaths(List<String> propertyPaths) {\r
+               List<String> result = new ArrayList<String>();\r
+               for (String facadePath : propertyPaths){\r
+                       // collecting areas (named area)\r
+                       if (facadePath.startsWith("collectingAreas")){\r
+                               facadePath = "gatheringEvent." + facadePath;\r
+                               result.add(facadePath);\r
+                       }\r
+                       // collector (agentBase)\r
+                       else if (facadePath.startsWith("collector")){\r
+                               facadePath = facadePath.replace("collector", "gatheringEvent.actor");\r
+                               result.add(facadePath);\r
+                       }\r
+                       // exactLocation (agentBase)\r
+                       else if (facadePath.startsWith("exactLocation")){\r
+                               facadePath = "gatheringEvent." + facadePath;\r
+                               result.add(facadePath);\r
+                       }\r
+                       // gatheringPeriod (TimePeriod)\r
+                       else if (facadePath.startsWith("gatheringPeriod")){\r
+                               facadePath = facadePath.replace("gatheringPeriod", "gatheringEvent.timeperiod");\r
+                               result.add(facadePath);\r
+                       }\r
+                       // (locality/ localityLanguage , LanguageString)\r
+                       else if (facadePath.startsWith("locality")){\r
+                               facadePath = "gatheringEvent." + facadePath;\r
+                               result.add(facadePath);\r
+                       }\r
+                       \r
+                       //*********** FIELD OBJECT ************\r
+                       // fieldObjectDefinitions (Map<language, languageString)\r
+                       else if (facadePath.startsWith("fieldObjectDefinitions")){\r
+                               // TODO or definition ???\r
+                               facadePath = facadePath.replace("fieldObjectDefinitions", "description");\r
+                               result.add(facadePath);\r
+                       }\r
+                       // fieldObjectMedia  (Media)\r
+                       else if (facadePath.startsWith("fieldObjectMedia")){\r
+                               // TODO ??? \r
+                               facadePath = facadePath.replace("fieldObjectMedia", "descriptions.elements.media");\r
+                               result.add(facadePath);\r
+                       }\r
+                       \r
+                       //Gathering Event will always be added\r
+                       result.add("gatheringEvent");\r
+                       \r
+               }\r
+               \r
+/*\r
+               Gathering Event\r
+               ====================\r
+               - gatheringEvent (GatheringEvent)\r
+\r
+               Field Object\r
+               =================\r
+               - ecology/ ecologyAll (String)  ???\r
+               - plant description (like ecology)\r
+               \r
+               - fieldObjectImageGallery (SpecimenDescription)  - is automatically initialized via fieldObjectMedia\r
+\r
+*/\r
+               \r
+               return result;\r
+       }\r
+       \r
+       /**\r
+        * 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
+       private List<String> getDerivedUnitPropertyPaths(List<String> propertyPaths) {\r
+               List<String> result = new ArrayList<String>();\r
+               for (String facadePath : propertyPaths){\r
+                       // determinations (DeterminationEvent)\r
+                       if (facadePath.startsWith("determinations")){\r
+                               facadePath = "" + facadePath;  //no change\r
+                               result.add(facadePath);\r
+                       }\r
+                       // storedUnder (TaxonNameBase)\r
+                       else if (facadePath.startsWith("storedUnder")){\r
+                               facadePath = "" + facadePath;  //no change\r
+                               result.add(facadePath);\r
+                       }\r
+                       // sources (IdentifiableSource)\r
+                       else if (facadePath.startsWith("sources")){\r
+                               facadePath = "" + facadePath;  //no change\r
+                               result.add(facadePath);\r
+                       }\r
+                       // collection (Collection)\r
+                       else if (facadePath.startsWith("collection")){\r
+                               facadePath = "" + facadePath;  //no change\r
+                               result.add(facadePath);\r
+                       }\r
+                       // (locality/ localityLanguage , LanguageString)\r
+                       else if (facadePath.startsWith("locality")){\r
+                               facadePath = "gatheringEvent." + facadePath;\r
+                               result.add(facadePath);\r
+                       }\r
+               \r
+                       //*********** FIELD OBJECT ************\r
+                       // derivedUnitDefinitions (Map<language, languageString)\r
+                       else if (facadePath.startsWith("derivedUnitDefinitions")){\r
+                               // TODO or definition ???\r
+                               facadePath = facadePath.replace("derivedUnitDefinitions", "description");\r
+                               result.add(facadePath);\r
+                       }\r
+                       \r
+                       // derivedUnitMedia  (Media)\r
+                       else if (facadePath.startsWith("derivedUnitMedia")){\r
+                               // TODO ??? \r
+                               facadePath = facadePath.replace("derivedUnitMedia", "descriptions.elements.media");\r
+                               result.add(facadePath);\r
+                       }\r
+                       \r
+               }\r
+               \r
+/*\r
+               //TODO\r
+               Derived Unit\r
+               =====================\r
+               \r
+               - derivedUnitImageGallery (SpecimenDescription)  - is automatically initialized via derivedUnitMedia\r
+               \r
+               - derivationEvent (DerivationEvent)  - will always be initialized\r
+               - duplicates (??? Specimen???) ???\r
+*/\r
+               \r
+               return result;\r
+       }\r
+\r
        /**\r
         * \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
-/**\r
-        * @param b\r
- * @throws DerivedUnitFacadeNotSupportedException \r
+\r
+       /**\r
+        * @param feature\r
+        * @param createIfNotExists\r
+        * @param isImageGallery\r
+        * @return\r
+        * @throws DerivedUnitFacadeNotSupportedException\r
+        */\r
+       private TextData initializeFieldObjectTextDataWithSupportTest(Feature feature, boolean createIfNotExists, boolean isImageGallery) throws DerivedUnitFacadeNotSupportedException {\r
+               //field object\r
+               FieldObservation fieldObject = getFieldObservation(createIfNotExists) ;\r
+               if (fieldObject == null){\r
+                       return null;\r
+               }\r
+               return inititializeTextDataWithSupportTest(feature, fieldObject, createIfNotExists, isImageGallery);\r
+       }\r
+\r
+\r
+       /**\r
+        * @param feature\r
+        * @param specimen\r
+        * @param createIfNotExists\r
+        * @param isImageGallery\r
+        * @return\r
+        * @throws DerivedUnitFacadeNotSupportedException\r
         */\r
-       private TextData initializeFieldObjectTextDataWithSupportTest(Feature feature, boolean createIfNotExists) throws DerivedUnitFacadeNotSupportedException {\r
-               if (feature == null){\r
+       private TextData inititializeTextDataWithSupportTest(Feature feature, SpecimenOrObservationBase specimen, boolean createIfNotExists, \r
+                               boolean isImageGallery) throws DerivedUnitFacadeNotSupportedException {\r
+               if (feature == null ){\r
                        return null;\r
                }\r
                TextData textData = null;\r
@@ -237,15 +467,15 @@ public class DerivedUnitFacade {
                        textData = TextData.NewInstance(feature);\r
                }\r
                \r
-               //field object\r
-               FieldObservation fieldObject = getFieldObservation(createIfNotExists) ;\r
-               if (fieldObject == null){\r
-                       return null;\r
+               Set<SpecimenDescription> descriptions;\r
+               if (isImageGallery){\r
+                       descriptions = specimen.getSpecimenDescriptionImageGallery();\r
+               }else{\r
+                       descriptions = specimen.getSpecimenDescriptions(false);\r
                }\r
-               Set<SpecimenDescription> descriptions = fieldObject.getSpecimenDescriptions(false);\r
                if (descriptions.size() == 0){\r
                        if (createIfNotExists){\r
-                               SpecimenDescription newSpecimenDescription = SpecimenDescription.NewInstance(fieldObject);\r
+                               SpecimenDescription newSpecimenDescription = SpecimenDescription.NewInstance(specimen);\r
                                newSpecimenDescription.addElement(textData);\r
                                return textData;\r
                        }else{\r
@@ -255,7 +485,7 @@ public class DerivedUnitFacade {
                Set<DescriptionElementBase> existingTextData = new HashSet<DescriptionElementBase>();\r
                for (SpecimenDescription description : descriptions){\r
                        for (DescriptionElementBase element: description.getElements()){\r
-                               if (element.isInstanceOf(TextData.class) && feature.equals(element.getFeature()) ){\r
+                               if (element.isInstanceOf(TextData.class) && ( feature.equals(element.getFeature() )|| isImageGallery ) ){\r
                                        existingTextData.add(element);\r
                                }\r
                        }\r
@@ -271,21 +501,51 @@ 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
-       private List<Media> setDerivedUnitImageGalleryMedia() throws DerivedUnitFacadeNotSupportedException{\r
-               if (specimenMedia == null){\r
-                       specimenMedia = getImageGalleryMedia(derivedUnit, "Specimen");\r
+       private TextData getDerivedUnitImageGalleryTextData(boolean createIfNotExists) throws DerivedUnitFacadeNotSupportedException{\r
+               if (this.derivedUnitMediaTextData == null && createIfNotExists){\r
+                       this.derivedUnitMediaTextData = getImageGalleryTextData(derivedUnit, "Specimen");\r
                }\r
-               return specimenMedia;\r
+               return this.derivedUnitMediaTextData;\r
        }\r
-\r
-       private List<Media> setObservationImageGalleryMedia() throws DerivedUnitFacadeNotSupportedException{\r
-               if (fieldObservationMedia == null){\r
-                       fieldObservationMedia = getImageGalleryMedia(fieldObservation, "Field observation");\r
+       \r
+       private TextData getObservationImageGalleryTextData(boolean createIfNotExists) throws DerivedUnitFacadeNotSupportedException{\r
+               if (this.fieldObjectMediaTextData == null && createIfNotExists){\r
+                       this.fieldObjectMediaTextData = getImageGalleryTextData(fieldObservation, "Field observation");\r
                }\r
-               return fieldObservationMedia;\r
+               return this.fieldObjectMediaTextData;\r
        }\r
 \r
        \r
@@ -326,6 +586,22 @@ public class DerivedUnitFacade {
        \r
        //*********** MEDIA METHODS ******************************\r
        \r
+//     /**\r
+//      * Returns the media list for a specimen. Throws an exception if the existing specimen descriptions\r
+//      * are not supported by this facade.\r
+//      * @param specimen the specimen the media belongs to\r
+//      * @param specimenExceptionText text describing the specimen for exception messages\r
+//      * @return\r
+//      * @throws DerivedUnitFacadeNotSupportedException\r
+//      */\r
+//     private List<Media> getImageGalleryMedia(SpecimenOrObservationBase specimen, String specimenExceptionText) throws DerivedUnitFacadeNotSupportedException{\r
+//             List<Media> result;\r
+//             SpecimenDescription imageGallery = getImageGalleryWithSupportTest(specimen, specimenExceptionText, true);\r
+//             TextData textData = getImageTextDataWithSupportTest(imageGallery, specimenExceptionText);\r
+//             result = textData.getMedia();\r
+//             return result;\r
+//     }\r
+       \r
        /**\r
         * Returns the media list for a specimen. Throws an exception if the existing specimen descriptions\r
         * are not supported by this facade.\r
@@ -334,11 +610,10 @@ public class DerivedUnitFacade {
         * @return\r
         * @throws DerivedUnitFacadeNotSupportedException\r
         */\r
-       private List<Media> getImageGalleryMedia(SpecimenOrObservationBase specimen, String specimenExceptionText) throws DerivedUnitFacadeNotSupportedException{\r
-               List<Media> result;\r
+       private TextData getImageGalleryTextData(SpecimenOrObservationBase specimen, String specimenExceptionText) throws DerivedUnitFacadeNotSupportedException{\r
+               TextData result;\r
                SpecimenDescription imageGallery = getImageGalleryWithSupportTest(specimen, specimenExceptionText, true);\r
-               TextData textData = getImageTextDataWithSupportTest(imageGallery, specimenExceptionText);\r
-               result = textData.getMedia();\r
+               result = getImageTextDataWithSupportTest(imageGallery, specimenExceptionText);\r
                return result;\r
        }\r
        \r
@@ -419,11 +694,12 @@ public class DerivedUnitFacade {
         * Returns the image gallery for a specimen. If there are multiple specimen descriptions\r
         * marked as image galleries an arbitrary one is chosen.\r
         * If no image gallery exists, a new one is created if <code>createNewIfNotExists</code>\r
-        * is <code>true</code>.\r
+        * is <code>true</code>.<Br>\r
+        * If specimen is <code>null</code> a null pointer exception is thrown.\r
         * @param createNewIfNotExists\r
         * @return\r
         */\r
-       private SpecimenDescription getImageGallery(SpecimenOrObservationBase<?> specimen, boolean createNewIfNotExists) {\r
+       private SpecimenDescription getImageGallery(SpecimenOrObservationBase<?> specimen, boolean createIfNotExists) {\r
                SpecimenDescription result = null;\r
                Set<SpecimenDescription> descriptions= specimen.getSpecimenDescriptions();\r
                for (SpecimenDescription description : descriptions){\r
@@ -432,7 +708,7 @@ public class DerivedUnitFacade {
                                break;\r
                        }\r
                }\r
-               if (result == null && createNewIfNotExists){\r
+               if (result == null && createIfNotExists){\r
                        result = SpecimenDescription.NewInstance(specimen);\r
                        result.setImageGallery(true);\r
                }\r
@@ -448,7 +724,7 @@ public class DerivedUnitFacade {
         */\r
        private boolean addMedia(Media media, SpecimenOrObservationBase<?> specimen) throws DerivedUnitFacadeNotSupportedException {\r
                if (media != null){\r
-                       List<Media> mediaList = getMedia(specimen);\r
+                       List<Media> mediaList = getMedia(specimen, true);\r
                        return mediaList.add(media);\r
                }else{\r
                        return false;\r
@@ -463,10 +739,15 @@ public class DerivedUnitFacade {
         * @throws DerivedUnitFacadeNotSupportedException\r
         */\r
        private boolean removeMedia(Media media, SpecimenOrObservationBase<?> specimen) throws DerivedUnitFacadeNotSupportedException {\r
-               List<Media> mediaList = getMedia(specimen);\r
+               List<Media> mediaList = getMedia(specimen, true);\r
                return mediaList == null ? null : mediaList.remove(media);\r
        }\r
 \r
+       private List<Media> getMedia(SpecimenOrObservationBase<?> specimen, boolean createIfNotExists) throws DerivedUnitFacadeNotSupportedException {\r
+               TextData textData = getMediaTextData(specimen, createIfNotExists);\r
+               return textData == null ? null : textData.getMedia();\r
+       }\r
+       \r
        /**\r
         * Returns the one media list of a specimen which is part of the only image gallery that \r
         * this specimen is part of.<BR>\r
@@ -475,16 +756,37 @@ public class DerivedUnitFacade {
         * @return\r
         * @throws DerivedUnitFacadeNotSupportedException\r
         */\r
-       private List<Media> getMedia(SpecimenOrObservationBase<?> specimen) throws DerivedUnitFacadeNotSupportedException {\r
+//     private List<Media> getMedia(SpecimenOrObservationBase<?> specimen) throws DerivedUnitFacadeNotSupportedException {\r
+//             if (specimen == null){\r
+//                     return null;\r
+//             }\r
+//             if (specimen == this.derivedUnit){\r
+//                     return getDerivedUnitImageGalleryMedia();\r
+//             }else if (specimen == this.fieldObservation){\r
+//                     return getObservationImageGalleryTextData();\r
+//             }else{\r
+//                     return getImageGalleryMedia(specimen, "Undefined specimen ");\r
+//             }\r
+//     }\r
+       \r
+       /**\r
+        * Returns the one media list of a specimen which is part of the only image gallery that \r
+        * this specimen is part of.<BR>\r
+        * If these conditions are not hold an exception is thrwon.\r
+        * @param specimen\r
+        * @return\r
+        * @throws DerivedUnitFacadeNotSupportedException\r
+        */\r
+       private TextData getMediaTextData(SpecimenOrObservationBase<?> specimen, boolean createIfNotExists) throws DerivedUnitFacadeNotSupportedException {\r
                if (specimen == null){\r
                        return null;\r
                }\r
                if (specimen == this.derivedUnit){\r
-                       return setDerivedUnitImageGalleryMedia();\r
+                       return getDerivedUnitImageGalleryTextData(createIfNotExists);\r
                }else if (specimen == this.fieldObservation){\r
-                       return setObservationImageGalleryMedia();\r
+                       return getObservationImageGalleryTextData(createIfNotExists);\r
                }else{\r
-                       return getImageGalleryMedia(specimen, "Undefined specimen ");\r
+                       return getImageGalleryTextData(specimen, "Undefined specimen ");\r
                }\r
        }\r
        \r
@@ -493,6 +795,17 @@ public class DerivedUnitFacade {
        \r
 // ****************** Gathering Event *********************************/\r
        \r
+       //country\r
+       @Transient\r
+       public NamedArea getCountry(){\r
+               return  (hasGatheringEvent() ? getGatheringEvent(true).getCountry() : null);\r
+       }\r
+       \r
+       public void setCountry(NamedArea country){\r
+               getGatheringEvent(true).setCountry(country);\r
+       }\r
+       \r
+       \r
        //Collecting area\r
        public void addCollectingArea(NamedArea area) {\r
                getGatheringEvent(true).addCollectingArea(area);\r
@@ -502,6 +815,7 @@ public class DerivedUnitFacade {
                        getGatheringEvent(true).addCollectingArea(area);\r
                }\r
        }\r
+       @Transient\r
        public Set<NamedArea> getCollectingAreas() {\r
                return  (hasGatheringEvent() ? getGatheringEvent(true).getCollectingAreas() : null);\r
        }\r
@@ -516,6 +830,7 @@ public class DerivedUnitFacade {
         * @see #getAbsoluteElevationError()\r
         * @see #getAbsoluteElevationRange()\r
         **/\r
+       @Transient\r
        public Integer getAbsoluteElevation() {\r
                return (hasGatheringEvent() ? getGatheringEvent(true).getAbsoluteElevation() : null);\r
        }\r
@@ -524,6 +839,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //absolute elevation error\r
+       @Transient\r
        public Integer getAbsoluteElevationError() {\r
                return (hasGatheringEvent() ? getGatheringEvent(true).getAbsoluteElevationError() : null);\r
        }\r
@@ -537,6 +853,7 @@ public class DerivedUnitFacade {
         * @see #setAbsoluteElevationRange(Integer, Integer)\r
         * @see #getAbsoluteElevationMaximum()\r
         */\r
+       @Transient\r
        public Integer getAbsoluteElevationMinimum(){\r
                if ( ! hasGatheringEvent() ){\r
                        return null;\r
@@ -553,6 +870,7 @@ public class DerivedUnitFacade {
         * @see #setAbsoluteElevationRange(Integer, Integer)\r
         * @see #getAbsoluteElevationMinimum()\r
         */\r
+       @Transient\r
        public Integer getAbsoluteElevationMaximum(){\r
                if ( ! hasGatheringEvent() ){\r
                        return null;\r
@@ -613,6 +931,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //collector\r
+       @Transient\r
        public AgentBase getCollector() {\r
                return  (hasGatheringEvent() ? getGatheringEvent(true).getCollector() : null);\r
        }\r
@@ -621,6 +940,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //collecting method\r
+       @Transient\r
        public String getCollectingMethod() {\r
                return  (hasGatheringEvent() ? getGatheringEvent(true).getCollectingMethod() : null);\r
        }\r
@@ -629,6 +949,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //distance to ground\r
+       @Transient\r
        public Integer getDistanceToGround() {\r
                return  (hasGatheringEvent() ? getGatheringEvent(true).getDistanceToGround() : null);\r
        }\r
@@ -637,6 +958,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //distance to water surface\r
+       @Transient\r
        public Integer getDistanceToWaterSurface() {\r
                return  (hasGatheringEvent() ? getGatheringEvent(true).getDistanceToWaterSurface() : null);\r
        }\r
@@ -645,12 +967,13 @@ public class DerivedUnitFacade {
        }\r
 \r
        //exact location\r
+       @Transient\r
        public Point getExactLocation() {\r
                return  (hasGatheringEvent() ? getGatheringEvent(true).getExactLocation() : null );\r
        }\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
@@ -670,6 +993,7 @@ public class DerivedUnitFacade {
        }\r
        \r
        //gathering event description\r
+       @Transient\r
        public String getGatheringEventDescription() {\r
                return  (hasGatheringEvent() ? getGatheringEvent(true).getDescription() : null);\r
        }\r
@@ -678,6 +1002,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //gatering period\r
+       @Transient\r
        public TimePeriod getGatheringPeriod() {\r
                return (hasGatheringEvent() ? getGatheringEvent(true).getTimeperiod() : null);\r
        }\r
@@ -686,9 +1011,15 @@ public class DerivedUnitFacade {
        }\r
 \r
        //locality\r
+       @Transient\r
        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
                if(locality != null){\r
@@ -696,6 +1027,11 @@ 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
                if(locality != null){\r
@@ -742,7 +1078,8 @@ public class DerivedUnitFacade {
        public boolean hasGatheringEvent(){\r
                return (getGatheringEvent(false) != null);\r
        }\r
-       public GatheringEvent getGatheringEvent() {\r
+       \r
+       public GatheringEvent innerGatheringEvent() {\r
                return getGatheringEvent(false);\r
        }\r
        \r
@@ -768,6 +1105,7 @@ public class DerivedUnitFacade {
        }\r
        \r
        //ecology\r
+       @Transient\r
        public String getEcology(){\r
                return getEcology(Language.DEFAULT());\r
        }\r
@@ -779,13 +1117,22 @@ 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
                        try {\r
-                               ecology = initializeFieldObjectTextDataWithSupportTest(Feature.ECOLOGY(), true);\r
+                               ecology = initializeFieldObjectTextDataWithSupportTest(Feature.ECOLOGY(), false, false);\r
                        } catch (DerivedUnitFacadeNotSupportedException e) {\r
                                throw new IllegalStateException(notSupportMessage, e);\r
                        }\r
+                       if (ecology == null){\r
+                               return new HashMap<Language, LanguageString>();\r
+                       }\r
                }\r
                return ecology.getMultilanguageText();\r
        }\r
@@ -799,7 +1146,7 @@ public class DerivedUnitFacade {
                }\r
                if (ecology == null){\r
                        try {\r
-                               ecology = initializeFieldObjectTextDataWithSupportTest(Feature.ECOLOGY(), true);\r
+                               ecology = initializeFieldObjectTextDataWithSupportTest(Feature.ECOLOGY(), true, false);\r
                        } catch (DerivedUnitFacadeNotSupportedException e) {\r
                                throw new IllegalStateException(notSupportMessage, e);\r
                        }\r
@@ -807,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
@@ -825,6 +1172,7 @@ public class DerivedUnitFacade {
 \r
        \r
        //plant description\r
+       @Transient\r
        public String getPlantDescription(){\r
                return getPlantDescription(null);\r
        }\r
@@ -839,13 +1187,22 @@ 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
                        try {\r
-                               plantDescription = initializeFieldObjectTextDataWithSupportTest(Feature.DESCRIPTION(), true);\r
+                               plantDescription = initializeFieldObjectTextDataWithSupportTest(Feature.DESCRIPTION(), false, false);\r
                        } catch (DerivedUnitFacadeNotSupportedException e) {\r
                                throw new IllegalStateException(notSupportMessage, e);\r
                        }\r
+                       if (plantDescription == null){\r
+                               return new HashMap<Language, LanguageString>();\r
+                       }\r
                }\r
                return plantDescription.getMultilanguageText();\r
        }\r
@@ -858,7 +1215,7 @@ public class DerivedUnitFacade {
                }\r
                if (plantDescription == null){\r
                        try {\r
-                               plantDescription = initializeFieldObjectTextDataWithSupportTest(Feature.DESCRIPTION(), true);\r
+                               plantDescription = initializeFieldObjectTextDataWithSupportTest(Feature.DESCRIPTION(), true, false);\r
                        } catch (DerivedUnitFacadeNotSupportedException e) {\r
                                throw new IllegalStateException(notSupportMessage, e);\r
                        }\r
@@ -866,19 +1223,18 @@ 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
                setPlantDescription(null, language);\r
        }\r
        \r
-\r
-       \r
        //field object definition\r
        public void addFieldObjectDefinition(String text, Language language) {\r
                getFieldObservation(true).addDefinition(text, language);\r
        }\r
+       @Transient\r
        public Map<Language, LanguageString> getFieldObjectDefinition() {\r
                if (! hasFieldObservation()){\r
                        return new HashMap<Language, LanguageString>();\r
@@ -922,16 +1278,55 @@ public class DerivedUnitFacade {
                        return (getImageGallery(fieldObservation, false) != null);\r
                }\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
+       public SpecimenDescription getFieldObjectImageGallery(boolean createIfNotExists){\r
+               TextData textData;\r
+               try {\r
+                       textData = initializeFieldObjectTextDataWithSupportTest(Feature.IMAGE(), createIfNotExists, true);\r
+               } catch (DerivedUnitFacadeNotSupportedException e) {\r
+                       throw new IllegalStateException(notSupportMessage, e);\r
+               }\r
+               if (textData != null){\r
+                       return CdmBase.deproxy(textData.getInDescription(), SpecimenDescription.class);\r
+               }else{\r
+                       return null;\r
+               }\r
+       }\r
        /**\r
         * Returns the media for the field object.<BR>\r
-        * Please handle with care as <B>this method will create an empty image gallery</B>\r
-        * if it does not yet exist. Use {@link #hasFieldObjectImageGallery()} first\r
-        * to test if an image gallery exists at all to avoid creating an empty gallery.\r
         * @return\r
         */\r
+       @Transient\r
        public List<Media> getFieldObjectMedia() {\r
                try {\r
-                       return getMedia(getFieldObservation(false));\r
+                       List<Media> result = getMedia(getFieldObservation(false), false);\r
+                       return result == null ? new ArrayList<Media>() : result;\r
                } catch (DerivedUnitFacadeNotSupportedException e) {\r
                        throw new IllegalStateException(notSupportMessage, e);\r
                }\r
@@ -945,6 +1340,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //field number\r
+       @Transient\r
        public String getFieldNumber() {\r
                if (! hasFieldObservation()){\r
                        return null;\r
@@ -956,8 +1352,23 @@ 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
        public String getFieldNotes() {\r
                if (! hasFieldObservation()){\r
                        return null;\r
@@ -971,6 +1382,7 @@ public class DerivedUnitFacade {
 \r
 \r
        //individual counts\r
+       @Transient\r
        public Integer getIndividualCount() {\r
                return (hasFieldObservation()? getFieldObservation(true).getIndividualCount() : null );\r
        }\r
@@ -979,6 +1391,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //life stage\r
+       @Transient\r
        public Stage getLifeStage() {\r
                return (hasFieldObservation()? getFieldObservation(true).getLifeStage() : null );\r
        }\r
@@ -987,6 +1400,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //sex\r
+       @Transient\r
        public Sex getSex() {\r
                return (hasFieldObservation()? getFieldObservation(true).getSex() : null );\r
        }\r
@@ -1004,7 +1418,7 @@ public class DerivedUnitFacade {
         * Returns the field observation as an object.\r
         * @return\r
         */\r
-       public FieldObservation getFieldObservation(){\r
+       public FieldObservation innerFieldObservation(){\r
                return getFieldObservation(false);\r
        }\r
 \r
@@ -1015,6 +1429,7 @@ public class DerivedUnitFacade {
        public FieldObservation getFieldObservation(boolean createIfNotExists){\r
                if (fieldObservation == null && createIfNotExists){\r
                        fieldObservation = FieldObservation.NewInstance();\r
+                       fieldObservation.addPropertyChangeListener(getNewEventPropagationListener());\r
                        DerivationEvent derivationEvent = getDerivationEvent(true);\r
                        derivationEvent.addOriginal(fieldObservation);\r
                }\r
@@ -1023,12 +1438,15 @@ public class DerivedUnitFacade {
 \r
        \r
 \r
+\r
+       \r
 //****************** Specimen **************************************************       \r
        \r
        //Definition\r
        public void addDerivedUnitDefinition(String text, Language language) {\r
                derivedUnit.addDefinition(text, language);\r
        }\r
+       @Transient\r
        public Map<Language, LanguageString> getDerivedUnitDefinitions(){\r
                return this.derivedUnit.getDefinition();\r
        }\r
@@ -1049,6 +1467,7 @@ public class DerivedUnitFacade {
        public void addDetermination(DeterminationEvent determination) {\r
                derivedUnit.addDetermination(determination);\r
        }\r
+       @Transient\r
        public Set<DeterminationEvent> getDeterminations() {\r
                return derivedUnit.getDeterminations();\r
        }\r
@@ -1068,19 +1487,65 @@ public class DerivedUnitFacade {
         * Returns true, if an image gallery exists for the specimen.<BR>\r
         * Returns also <code>true</code> if the image gallery is empty. \r
         */\r
-       public boolean hasSpecimenImageGallery(){\r
+       public boolean hasDerivedUnitImageGallery(){\r
                return (getImageGallery(derivedUnit, false) != null);\r
-       }       \r
+       }\r
+       \r
+       public SpecimenDescription getDerivedUnitImageGallery(boolean createIfNotExists){\r
+               TextData textData;\r
+               try {\r
+                       textData = inititializeTextDataWithSupportTest(Feature.IMAGE(), derivedUnit, createIfNotExists, true);\r
+               } catch (DerivedUnitFacadeNotSupportedException e) {\r
+                       throw new IllegalStateException(notSupportMessage, e);\r
+               }\r
+               if (textData != null){\r
+                       return CdmBase.deproxy(textData.getInDescription(), SpecimenDescription.class);\r
+               }else{\r
+                       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
-        * Please handle with care as <B>this method will create an empty image gallery</B>\r
-        * if it does not yet exist. Use {@link #hasFieldObjectImageGallery()} first\r
-        * to test if an image gallery exists at all to avoid creating an empty gallery.\r
         * @return\r
         */\r
+       @Transient\r
        public List<Media> getDerivedUnitMedia() {\r
                try {\r
-                       return getMedia(derivedUnit);\r
+                       List<Media> result = getMedia(derivedUnit, false);\r
+                       return result == null ? new ArrayList<Media>() : result;\r
                } catch (DerivedUnitFacadeNotSupportedException e) {\r
                        throw new IllegalStateException(notSupportMessage, e);\r
                }\r
@@ -1095,6 +1560,7 @@ public class DerivedUnitFacade {
 \r
        \r
        //Accession Number\r
+       @Transient\r
        public String getAccessionNumber() {\r
                return derivedUnit.getAccessionNumber();\r
        }\r
@@ -1102,7 +1568,7 @@ public class DerivedUnitFacade {
                derivedUnit.setAccessionNumber(accessionNumber);\r
        }\r
 \r
-       //Catalog Number\r
+       @Transient\r
        public String getCatalogNumber() {\r
                return derivedUnit.getCatalogNumber();\r
        }\r
@@ -1110,6 +1576,15 @@ public class DerivedUnitFacade {
                derivedUnit.setCatalogNumber(catalogNumber);\r
        }\r
 \r
+       @Transient\r
+       public String getBarcode() {\r
+               return derivedUnit.getBarcode();\r
+       }\r
+       public void setBarcode(String barcode) {\r
+               derivedUnit.setBarcode(barcode);\r
+       }\r
+\r
+       \r
        //Preservation Method\r
        \r
        /**\r
@@ -1117,11 +1592,16 @@ public class DerivedUnitFacade {
         * @see #DerivedUnitType\r
         * @return\r
         */\r
+       @Transient\r
        public PreservationMethod getPreservationMethod() throws MethodNotSupportedByDerivedUnitTypeException {\r
                if (derivedUnit.isInstanceOf(Specimen.class)){\r
                        return CdmBase.deproxy(derivedUnit, Specimen.class).getPreservation();\r
                }else{\r
-                       throw new MethodNotSupportedByDerivedUnitTypeException("A preservation method is only available in derived units of type 'Specimen' or 'Fossil'");\r
+                       if (this.config.isThrowExceptionForNonSpecimenPreservationMethodRequest()){\r
+                               throw new MethodNotSupportedByDerivedUnitTypeException("A preservation method is only available in derived units of type 'Specimen' or 'Fossil'");\r
+                       }else{\r
+                               return null;\r
+                       }\r
                }\r
        }\r
        /**\r
@@ -1133,12 +1613,16 @@ public class DerivedUnitFacade {
                if (derivedUnit.isInstanceOf(Specimen.class)){\r
                        CdmBase.deproxy(derivedUnit, Specimen.class).setPreservation(preservation);\r
                }else{\r
-                       throw new MethodNotSupportedByDerivedUnitTypeException("A preservation method is only available in derived units of type 'Specimen' or 'Fossil'");\r
-                       \r
+                       if (this.config.isThrowExceptionForNonSpecimenPreservationMethodRequest()){\r
+                               throw new MethodNotSupportedByDerivedUnitTypeException("A preservation method is only available in derived units of type 'Specimen' or 'Fossil'");\r
+                       }else{\r
+                               return;\r
+                       }\r
                }\r
        }\r
 \r
        //Stored under name\r
+       @Transient\r
        public TaxonNameBase getStoredUnder() {\r
                return derivedUnit.getStoredUnder();\r
        }\r
@@ -1147,6 +1631,7 @@ public class DerivedUnitFacade {
        }\r
 \r
        //colletors number\r
+       @Transient\r
        public String getCollectorsNumber() {\r
                return derivedUnit.getCollectorsNumber();\r
        }\r
@@ -1163,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
@@ -1172,7 +1660,7 @@ public class DerivedUnitFacade {
         * Returns the derived unit itself.\r
         * @return the derived unit\r
         */\r
-       public DerivedUnitBase getDerivedUnit() {\r
+       public DerivedUnitBase innerDerivedUnit() {\r
                return this.derivedUnit;\r
        }\r
        \r
@@ -1190,14 +1678,29 @@ public class DerivedUnitFacade {
                }\r
                return result;\r
        }\r
-       \r
-       public String getExsiccatum() {\r
-               logger.warn("Exsiccatum method not yet supported. Needs model change");\r
-               return null;\r
+       @Transient\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
@@ -1212,13 +1715,14 @@ 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
                return source;\r
        }\r
-       \r
+\r
+       @Transient\r
        public Set<IdentifiableSource> getSources(){\r
                return derivedUnit.getSources();\r
        }\r
@@ -1231,6 +1735,7 @@ public class DerivedUnitFacade {
        /**\r
         * @return the collection\r
         */\r
+       @Transient\r
        public Collection getCollection() {\r
                return derivedUnit.getCollection();\r
        }\r
@@ -1243,8 +1748,38 @@ public class DerivedUnitFacade {
                derivedUnit.setCollection(collection);\r
        }\r
        \r
+       //annotation    \r
+       public void addAnnotation(Annotation annotation){\r
+               this.derivedUnit.addAnnotation(annotation);\r
+       }\r
+\r
+       @Transient\r
+       public void getAnnotations(){\r
+               this.derivedUnit.getAnnotations();\r
+       }\r
+       \r
+       public void removeAnnotation(Annotation annotation){\r
+               this.derivedUnit.removeAnnotation(annotation);\r
+       }\r
+       \r
        \r
+// ******************************* Events *********************************************\r
+       \r
+       /**\r
+        * @return\r
+        */\r
+       private PropertyChangeListener getNewEventPropagationListener() {\r
+               PropertyChangeListener listener = new PropertyChangeListener(){\r
+                       @Override\r
+                       public void propertyChange(PropertyChangeEvent event) {\r
+                               derivedUnit.firePropertyChange(event);\r
+                       }\r
+                       \r
+               };\r
+               return listener;\r
+       }\r
 \r
+               \r
        \r
 \r
 //**************** Other Collections ***************************************************       \r
@@ -1279,6 +1814,8 @@ public class DerivedUnitFacade {
                //TODO check derivedUnitType\r
                getDerivationEvent(true).addDerivative(duplicateSpecimen);  \r
        }\r
+       \r
+       @Transient\r
        public Set<Specimen> getDuplicates(){\r
                Set<Specimen> result = new HashSet<Specimen>();\r
                if (hasDerivationEvent()){\r