setting mimetype during import
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / common / CdmImportBase.java
index c87ea2b36189421a3ed1bc8ff47712ba77d6283d..0df119d05fa68a8ee773e48d8b6af5d6d607bef1 100644 (file)
@@ -9,10 +9,44 @@
 \r
 package eu.etaxonomy.cdm.io.common;\r
 \r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+import java.util.Set;\r
+import java.util.UUID;\r
+\r
 import org.apache.log4j.Logger;\r
 \r
 import eu.etaxonomy.cdm.common.CdmUtils;\r
+import eu.etaxonomy.cdm.common.mediaMetaData.ImageMetaData;\r
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
+import eu.etaxonomy.cdm.io.common.mapping.IInputTransformer;\r
+import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;\r
+import eu.etaxonomy.cdm.model.common.AnnotationType;\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.model.common.DescriptionElementSource;\r
+import eu.etaxonomy.cdm.model.common.ExtensionType;\r
+import eu.etaxonomy.cdm.model.common.IOriginalSource;\r
+import eu.etaxonomy.cdm.model.common.ISourceable;\r
+import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
+import eu.etaxonomy.cdm.model.common.Language;\r
+import eu.etaxonomy.cdm.model.common.MarkerType;\r
+import eu.etaxonomy.cdm.model.common.TermVocabulary;\r
+import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
+import eu.etaxonomy.cdm.model.description.Feature;\r
+import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
+import eu.etaxonomy.cdm.model.location.NamedArea;\r
+import eu.etaxonomy.cdm.model.location.NamedAreaLevel;\r
+import eu.etaxonomy.cdm.model.location.NamedAreaType;\r
+import eu.etaxonomy.cdm.model.media.ImageFile;\r
+import eu.etaxonomy.cdm.model.media.Media;\r
+import eu.etaxonomy.cdm.model.media.MediaRepresentation;\r
+import eu.etaxonomy.cdm.model.name.NonViralName;\r
+import eu.etaxonomy.cdm.model.name.Rank;\r
 import eu.etaxonomy.cdm.model.reference.ReferenceBase;\r
+import eu.etaxonomy.cdm.model.taxon.Taxon;\r
 import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;\r
 \r
 /**\r
@@ -21,10 +55,10 @@ import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;
  * @version 1.0\r
  */\r
 public abstract class CdmImportBase<CONFIG extends IImportConfigurator, STATE extends ImportStateBase> extends CdmIoBase<STATE> implements ICdmImport<CONFIG, STATE>{\r
-       @SuppressWarnings("unused")\r
        private static Logger logger = Logger.getLogger(CdmImportBase.class);\r
 \r
-       protected TaxonomicTree makeTree(STATE state, ReferenceBase ref){\r
+       protected TaxonomicTree makeTree(STATE state, ReferenceBase reference){\r
+               ReferenceBase ref = CdmBase.deproxy(reference, ReferenceBase.class);\r
                String treeName = "TaxonTree (Import)";\r
                if (ref != null && CdmUtils.isNotEmpty(ref.getTitleCache())){\r
                        treeName = ref.getTitleCache();\r
@@ -32,9 +66,339 @@ public abstract class CdmImportBase<CONFIG extends IImportConfigurator, STATE ex
                TaxonomicTree tree = TaxonomicTree.NewInstance(treeName);\r
                tree.setReference(ref);\r
                \r
-               getTaxonService().saveTaxonomicTree(tree);\r
+\r
+               // use defined uuid for first tree\r
+               CONFIG config = (CONFIG)state.getConfig();\r
+               if (state.countTrees() < 1 ){\r
+                       tree.setUuid(config.getTaxonomicTreeUuid());\r
+               }\r
+               getTaxonTreeService().save(tree);\r
                state.putTree(ref, tree);\r
                return tree;\r
        }\r
        \r
+       \r
+       /**\r
+        * Alternative memory saving method variant of\r
+        * {@link #makeTree(STATE state, ReferenceBase ref)} which stores only the\r
+        * UUID instead of the full tree in the <code>ImportStateBase</code> by \r
+        * using <code>state.putTreeUuid(ref, tree);</code>\r
+        * \r
+        * @param state\r
+        * @param ref\r
+        * @return\r
+        */\r
+       protected TaxonomicTree makeTreeMemSave(STATE state, ReferenceBase ref){\r
+               String treeName = "TaxonTree (Import)";\r
+               if (ref != null && CdmUtils.isNotEmpty(ref.getTitleCache())){\r
+                       treeName = ref.getTitleCache();\r
+               }\r
+               TaxonomicTree tree = TaxonomicTree.NewInstance(treeName);\r
+               tree.setReference(ref);\r
+               \r
+\r
+               // use defined uuid for first tree\r
+               CONFIG config = (CONFIG)state.getConfig();\r
+               if (state.countTrees() < 1 ){\r
+                       tree.setUuid(config.getTaxonomicTreeUuid());\r
+               }\r
+               getTaxonTreeService().save(tree);\r
+               state.putTreeUuid(ref, tree);\r
+               return tree;\r
+       }\r
+       \r
+       \r
+       protected ExtensionType getExtensionType(STATE state, UUID uuid, String label, String text, String labelAbbrev){\r
+               ExtensionType extensionType = state.getExtensionType(uuid);\r
+               if (extensionType == null){\r
+                       extensionType = (ExtensionType)getTermService().find(uuid);\r
+                       if (extensionType == null){\r
+                               extensionType = ExtensionType.NewInstance(text, label, labelAbbrev);\r
+                               extensionType.setUuid(uuid);\r
+                               ExtensionType.DOI().getVocabulary().addTerm(extensionType);\r
+                               getTermService().save(extensionType);\r
+                       }\r
+                       state.putExtensionType(extensionType);\r
+               }\r
+               return extensionType;\r
+       }\r
+       \r
+       \r
+       protected MarkerType getMarkerType(STATE state, String keyString) {\r
+               IInputTransformer transformer = state.getTransformer();\r
+               MarkerType markerType = null;\r
+               try {\r
+                       markerType = transformer.getMarkerTypeByKey(keyString);\r
+               } catch (UndefinedTransformerMethodException e) {\r
+                       logger.info("getMarkerTypeByKey not yet implemented for this import");\r
+               }\r
+               if (markerType == null ){\r
+                       UUID uuid;\r
+                       try {\r
+                               uuid = transformer.getMarkerTypeUuid(keyString);\r
+                               return getMarkerType(state, uuid, keyString, keyString, keyString);\r
+                       } catch (UndefinedTransformerMethodException e) {\r
+                               logger.warn("getMarkerTypeUuid not yet implemented for this import");\r
+                       }\r
+               }\r
+               return null;\r
+       }\r
+       \r
+       protected MarkerType getMarkerType(STATE state, UUID uuid, String label, String text, String labelAbbrev){\r
+               MarkerType markerType = state.getMarkerType(uuid);\r
+               if (markerType == null){\r
+                       markerType = (MarkerType)getTermService().find(uuid);\r
+                       if (markerType == null){\r
+                               markerType = MarkerType.NewInstance(label, text, labelAbbrev);\r
+                               markerType.setUuid(uuid);\r
+                               MarkerType.COMPLETE().getVocabulary().addTerm(markerType);\r
+                               getTermService().save(markerType);\r
+                       }\r
+                       state.putMarkerType(markerType);\r
+               }\r
+               return markerType;\r
+       }\r
+       \r
+       protected AnnotationType getAnnotationType(STATE state, UUID uuid, String label, String text, String labelAbbrev){\r
+               AnnotationType annotationType = state.getAnnotationType(uuid);\r
+               if (annotationType == null){\r
+                       annotationType = (AnnotationType)getTermService().find(uuid);\r
+                       if (annotationType == null){\r
+                               annotationType = AnnotationType.NewInstance(label, text, labelAbbrev);\r
+                               annotationType.setUuid(uuid);\r
+                               AnnotationType.EDITORIAL().getVocabulary().addTerm(annotationType);\r
+                               getTermService().save(annotationType);\r
+                       }\r
+                       state.putAnnotationType(annotationType);\r
+               }\r
+               return annotationType;\r
+       }\r
+       \r
+       /**\r
+        * Returns a named area for a given uuid by first . If the named area does not\r
+        * @param state\r
+        * @param uuid\r
+        * @param label\r
+        * @param text\r
+        * @param labelAbbrev\r
+        * @param areaType\r
+        * @param level\r
+        * @return\r
+        */\r
+       protected NamedArea getNamedArea(STATE state, UUID uuid, String label, String text, String labelAbbrev, NamedAreaType areaType, NamedAreaLevel level){\r
+               NamedArea namedArea = state.getNamedArea(uuid);\r
+               if (namedArea == null){\r
+                       namedArea = (NamedArea)getTermService().find(uuid);\r
+                       if (namedArea == null){\r
+                               namedArea = NamedArea.NewInstance(text, label, labelAbbrev);\r
+                               namedArea.setType(areaType);\r
+                               namedArea.setLevel(level);\r
+                               namedArea.setUuid(uuid);\r
+                               getTermService().save(namedArea);\r
+                       }\r
+                       state.putNamedArea(namedArea);\r
+               }\r
+               return namedArea;\r
+       }\r
+       \r
+       /**\r
+        * Returns a feature for a given uuid by first ...\r
+        * @param state\r
+        * @param uuid\r
+        * @param label\r
+        * @param text\r
+        * @param labelAbbrev\r
+        * @return\r
+        */\r
+       protected Feature getFeature(STATE state, UUID uuid, String label, String text, String labelAbbrev){\r
+               if (uuid == null){\r
+                       return null;\r
+               }\r
+               Feature feature = state.getFeature(uuid);\r
+               if (feature == null){\r
+                       feature = (Feature)getTermService().find(uuid);\r
+                       if (feature == null){\r
+                               feature = Feature.NewInstance(text, label, labelAbbrev);\r
+                               feature.setUuid(uuid);\r
+                               feature.setSupportsTextData(true);\r
+                               //set vocabulary ; FIXME use another user-defined vocabulary\r
+                               UUID uuidFeatureVoc = UUID.fromString("b187d555-f06f-4d65-9e53-da7c93f8eaa8"); \r
+                               TermVocabulary<Feature> voc = getVocabularyService().find(uuidFeatureVoc);\r
+                               voc.addTerm(feature);\r
+                               getTermService().save(feature);\r
+                       }\r
+                       state.putFeature(feature);\r
+               }\r
+               return feature;\r
+       }\r
+\r
+       /**\r
+        * Returns a language for a given uuid by first ...\r
+        * @param state\r
+        * @param uuid\r
+        * @param label\r
+        * @param text\r
+        * @param labelAbbrev\r
+        * @return\r
+        */\r
+       protected Language getLanguage(STATE state, UUID uuid, String label, String text, String labelAbbrev){\r
+               if (uuid == null){\r
+                       return null;\r
+               }\r
+               Language language = state.getLanguage(uuid);\r
+               if (language == null){\r
+                       language = (Language)getTermService().find(uuid);\r
+                       if (language == null){\r
+                               language = Language.NewInstance(text, label, labelAbbrev);\r
+                               \r
+                               language.setUuid(uuid);\r
+                               //set vocabulary ; FIXME use another user-defined vocabulary\r
+                               UUID uuidLanguageVoc = UUID.fromString("45ac7043-7f5e-4f37-92f2-3874aaaef2de"); \r
+                               TermVocabulary<Language> voc = getVocabularyService().find(uuidLanguageVoc);\r
+                               voc.addTerm(language);\r
+                               getTermService().save(language);\r
+                       }\r
+                       state.putLanguage(language);\r
+               }\r
+               return language;\r
+       }\r
+       \r
+       /**\r
+        * Adds an orginal source to a sourceable objects (implemented for Identifiable entity and description element.\r
+        * If cdmBase is not sourceable nothing happens.\r
+        * TODO Move to DbImportBase once this exists.\r
+        * TODO also implemented in DbImportObjectCreationMapper (reduce redundance)\r
+        * @param rs\r
+        * @param cdmBase\r
+        * @param dbIdAttribute\r
+        * @param namespace\r
+        * @param citation\r
+        * @throws SQLException\r
+        */\r
+       public void addOriginalSource(CdmBase cdmBase, Object idAttributeValue, String namespace, ReferenceBase citation) throws SQLException {\r
+               if (cdmBase instanceof ISourceable ){\r
+                       IOriginalSource source;\r
+                       ISourceable sourceable = (ISourceable)cdmBase;\r
+                       Object id = idAttributeValue;\r
+                       String strId = String.valueOf(id);\r
+                       String microCitation = null;\r
+                       if (cdmBase instanceof IdentifiableEntity){\r
+                               source = IdentifiableSource.NewInstance(strId, namespace, citation, microCitation);\r
+                       }else if (cdmBase instanceof DescriptionElementBase){\r
+                               source = DescriptionElementSource.NewInstance(strId, namespace, citation, microCitation);\r
+                       }else{\r
+                               logger.warn("ISourceable not beeing identifiable entities or description element base are not yet supported. CdmBase is of type " + cdmBase.getClass().getName() + ". Original source not added.");\r
+                               return;\r
+                       }\r
+                       sourceable.addSource(source);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * @see #addOriginalSource(CdmBase, Object, String, ReferenceBase)\r
+        * @param rs\r
+        * @param cdmBase\r
+        * @param dbIdAttribute\r
+        * @param namespace\r
+        * @param citation\r
+        * @throws SQLException\r
+        */\r
+       public void addOriginalSource(ResultSet rs, CdmBase cdmBase, String dbIdAttribute, String namespace, ReferenceBase citation) throws SQLException {\r
+               Object id = rs.getObject(dbIdAttribute);\r
+               addOriginalSource(cdmBase, id, namespace, citation);\r
+       }\r
+       \r
+\r
+       /**\r
+        * If the child taxon is missing genus or species epithet information and the rank is below <i>genus</i>\r
+        * or <i>species</i> respectively the according epithets are taken from the parent taxon.\r
+        * If the name is an autonym and has no combination author/basionym author the authors are taken from\r
+        * the parent.\r
+        * @param parentTaxon\r
+        * @param childTaxon\r
+        */\r
+       protected void fillMissingEpithetsForTaxa(Taxon parentTaxon, Taxon childTaxon) {\r
+               NonViralName parentName = HibernateProxyHelper.deproxy(parentTaxon.getName(), NonViralName.class);\r
+               NonViralName childName = HibernateProxyHelper.deproxy(childTaxon.getName(), NonViralName.class);\r
+               fillMissingEpithets(parentName, childName);\r
+       }\r
+       \r
+       /**\r
+        * If the child name is missing genus or species epithet information and the rank is below <i>genus</i>\r
+        * or <i>species</i> respectively the according epithets are taken from the parent name.\r
+        * If the name is an autonym and has no combination author/basionym author the authors are taken from\r
+        * the parent.\r
+        * @param parentTaxon\r
+        * @param childTaxon\r
+        */\r
+       protected void fillMissingEpithets(NonViralName parentName, NonViralName childName) {\r
+               if (CdmUtils.isEmpty(childName.getGenusOrUninomial()) && childName.getRank().isLower(Rank.GENUS()) ){\r
+                       childName.setGenusOrUninomial(parentName.getGenusOrUninomial());\r
+               }\r
+               \r
+               if (CdmUtils.isEmpty(childName.getSpecificEpithet()) && childName.getRank().isLower(Rank.SPECIES()) ){\r
+                       childName.setSpecificEpithet(parentName.getSpecificEpithet());\r
+               }\r
+               if (childName.isAutonym() && childName.getCombinationAuthorTeam() == null && childName.getBasionymAuthorTeam() == null ){\r
+                       childName.setCombinationAuthorTeam(parentName.getCombinationAuthorTeam());\r
+                       childName.setBasionymAuthorTeam(parentName.getBasionymAuthorTeam());\r
+               }       \r
+       }\r
+       \r
+       /**\r
+        * Returns the image gallery for a taxon. If there are multiple taxon 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
+        * @param createNewIfNotExists\r
+        * @return\r
+        */\r
+       public TaxonDescription getTaxonDescription(Taxon taxon, boolean isImageGallery, boolean createNewIfNotExists) {\r
+               TaxonDescription result = null;\r
+               Set<TaxonDescription> descriptions= taxon.getDescriptions();\r
+               for (TaxonDescription description : descriptions){\r
+                       if (description.isImageGallery() == isImageGallery){\r
+                               result = description;\r
+                               break;\r
+                       }\r
+               }\r
+               if (result == null && createNewIfNotExists){\r
+                       result = TaxonDescription.NewInstance(taxon);\r
+                       result.setImageGallery(isImageGallery);\r
+               }\r
+               return result;\r
+       }\r
+       \r
+\r
+       /**\r
+        * @param derivedUnitFacade\r
+        * @param multimediaObject\r
+        * @throws MalformedURLException\r
+        */\r
+       protected Media getImageMedia(String multimediaObject, boolean readDataFromUrl) throws MalformedURLException {\r
+               if( multimediaObject == null){\r
+                       return null;\r
+               } else {\r
+                       ImageMetaData imd = ImageMetaData.newInstance();\r
+                       try {\r
+                               if (readDataFromUrl){\r
+                                       URL url = new URL(multimediaObject);\r
+                                       imd.readMetaData(url.toURI(), 0);\r
+                               }\r
+                       } catch (Exception e) {\r
+                               String message = "An error occurred when trying to read image meta data: " +  e.getMessage();\r
+                               logger.warn(message);\r
+                       }\r
+                       ImageFile imf = ImageFile.NewInstance(multimediaObject, null, imd);\r
+                       MediaRepresentation representation = MediaRepresentation.NewInstance();\r
+                       representation.setMimeType(imd.getMimeType());\r
+                       representation.addRepresentationPart(imf);\r
+                       Media media = Media.NewInstance();\r
+                       media.addRepresentation(representation);\r
+                               \r
+                       return media;\r
+               }\r
+       }\r
+\r
+       \r
 }\r