\r
package eu.etaxonomy.cdm.io.berlinModel.in;\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.Collection;\r
import java.util.HashSet;\r
-import java.util.Map;\r
import java.util.Set;\r
\r
import org.apache.log4j.Logger;\r
import org.springframework.stereotype.Component;\r
\r
import eu.etaxonomy.cdm.common.CdmUtils;\r
+import eu.etaxonomy.cdm.common.MediaMetaData.ImageMetaData;\r
import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;\r
import eu.etaxonomy.cdm.io.common.ICdmIO;\r
-import eu.etaxonomy.cdm.io.common.IImportConfigurator;\r
import eu.etaxonomy.cdm.io.common.MapWrapper;\r
import eu.etaxonomy.cdm.io.common.Source;\r
-import eu.etaxonomy.cdm.model.common.CdmBase;\r
+import eu.etaxonomy.cdm.model.common.Annotation;\r
+import eu.etaxonomy.cdm.model.common.DescriptionElementSource;\r
import eu.etaxonomy.cdm.model.common.Language;\r
+import eu.etaxonomy.cdm.model.common.Marker;\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.description.TextData;\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.reference.ReferenceBase;\r
import eu.etaxonomy.cdm.model.taxon.Taxon;\r
import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
public class BerlinModelFactsImport extends BerlinModelImportBase {\r
private static final Logger logger = Logger.getLogger(BerlinModelFactsImport.class);\r
\r
+ public static final String SEQUENCE_PREFIX = "ORDER: ";\r
+ \r
private int modCount = 10000;\r
\r
public BerlinModelFactsImport(){\r
* @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IImportConfigurator)\r
*/\r
@Override\r
- protected boolean doCheck(IImportConfigurator config){\r
+ protected boolean doCheck(BerlinModelImportState state){\r
boolean result = true;\r
- logger.warn("Checking for Facts not yet implemented");\r
- //result &= checkArticlesWithoutJournal(bmiConfig);\r
- //result &= checkPartOfJournal(bmiConfig);\r
- \r
+ BerlinModelImportConfigurator bmiConfig = state.getConfig();\r
+ logger.warn("Checking for Facts not yet fully implemented");\r
+ result &= checkDesignationRefsExist(bmiConfig);\r
return result;\r
}\r
\r
\r
private MapWrapper<Feature> invokeFactCategories(BerlinModelImportConfigurator bmiConfig){\r
\r
-// Map<Integer, Feature> featureMap = new HashMap<Integer, Feature>();\r
MapWrapper<Feature> result = bmiConfig.getFeatureMap();\r
-\r
Source source = bmiConfig.getSource();\r
-\r
\r
try {\r
//get data from database\r
* @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IImportConfigurator, eu.etaxonomy.cdm.api.application.CdmApplicationController, java.util.Map)\r
*/\r
@Override\r
- protected boolean doInvoke(BerlinModelImportState<BerlinModelImportConfigurator> state){\r
+ protected boolean doInvoke(BerlinModelImportState state) {\r
boolean result = true;\r
\r
MapWrapper<TaxonBase> taxonMap = (MapWrapper<TaxonBase>)state.getStore(ICdmIO.TAXON_STORE);\r
\r
MapWrapper<Feature> featureMap = invokeFactCategories(config);\r
\r
- //for testing only\r
- //TaxonBase taxonBase = Taxon.NewInstance(BotanicalName.NewInstance(null), null);\r
- \r
- \r
try {\r
//get data from database\r
String strQuery = \r
" FROM Fact " +\r
" INNER JOIN PTaxon ON Fact.PTNameFk = PTaxon.PTNameFk AND Fact.PTRefFk = PTaxon.PTRefFk " +\r
" LEFT OUTER JOIN RefDetail ON Fact.FactRefDetailFk = RefDetail.RefDetailId AND Fact.FactRefFk = RefDetail.RefFk " +\r
- " WHERE (1=1)";\r
+ " WHERE (1=1)" + \r
+ " ORDER By Sequence";\r
ResultSet rs = source.getResultSet(strQuery) ;\r
-\r
+ ReferenceBase<?> sourceRef = state.getConfig().getSourceReference();\r
+ \r
int i = 0;\r
- //for each reference\r
+ //for each fact\r
while (rs.next()){\r
try{\r
if ((i++ % modCount) == 0){ logger.info("Facts handled: " + (i-1));}\r
\r
- //Map<String, Object> valueMap = getValueMap(rs);\r
- \r
int factId = rs.getInt("factId");\r
- \r
- \r
Object taxonIdObj = rs.getObject("taxonId");\r
int taxonId = rs.getInt("taxonId");\r
Object factRefFkObj = rs.getObject("factRefFk");\r
int factRefFk = rs.getInt("factRefFk");\r
Object categoryFkObj = rs.getObject("factCategoryFk");\r
Integer categoryFk = rs.getInt("factCategoryFk");\r
- \r
String details = rs.getString("Details");\r
- // int ptDesignationRefFk = rs.getInt("PTDesignationRefFk");\r
- // String ptDesignation details = rs.getInt("PTDesignationRefDetailFk");\r
String fact = CdmUtils.Nz(rs.getString("Fact"));\r
String notes = CdmUtils.Nz(rs.getString("notes"));\r
+ Boolean doubtfulFlag = rs.getBoolean("DoubtfulFlag");\r
+ Boolean publishFlag = rs.getBoolean("publishFlag");\r
\r
+ TaxonBase taxonBase = getTaxon(taxonMap, taxonIdObj, taxonId);\r
+ Feature feature = getFeature(featureMap, categoryFkObj, categoryFk) ;\r
\r
- \r
- TaxonBase taxonBase;\r
- if (taxonIdObj != null){\r
- taxonBase = taxonMap.get(taxonId);\r
- }else{\r
- taxonBase = null;\r
- }\r
- Feature feature;\r
- if (categoryFkObj != null){\r
- feature = featureMap.get(categoryFk); \r
+ if (taxonBase == null){\r
+ logger.warn("Taxon for Fact " + factId + " does not exist in store");\r
+ result = false;\r
}else{\r
- feature = null;\r
- }\r
- \r
- if (taxonBase != null){\r
Taxon taxon;\r
if ( taxonBase instanceof Taxon ) {\r
taxon = (Taxon) taxonBase;\r
}else{\r
logger.warn("TaxonBase " + (taxonIdObj==null?"(null)":taxonIdObj) + " for Fact " + factId + " was not of type Taxon but: " + taxonBase.getClass().getSimpleName());\r
+ result = false;\r
continue;\r
}\r
\r
- TaxonDescription taxonDescription;\r
+ TaxonDescription taxonDescription = null;\r
Set<TaxonDescription> descriptionSet= taxon.getDescriptions();\r
- if (descriptionSet.size() > 0) {\r
- taxonDescription = descriptionSet.iterator().next(); \r
- }else{\r
- taxonDescription = TaxonDescription.NewInstance();\r
- taxon.addDescription(taxonDescription);\r
- }\r
\r
+ boolean isImage = false;\r
+ Media media = null;\r
+ //for diptera images\r
+ if (categoryFk == 51){ //TODO check also FactCategory string\r
+ isImage = true;\r
+ media = Media.NewInstance();\r
+ taxonDescription = makeImage(state, fact, media, descriptionSet, taxon);\r
+ if (taxonDescription == null){\r
+ continue;\r
+ }\r
+ }\r
+ //all others (no image)\r
+ else{ \r
+ for (TaxonDescription desc: descriptionSet){\r
+ if (! desc.isImageGallery()){\r
+ taxonDescription = desc;\r
+ }\r
+ }\r
+ if (taxonDescription == null){\r
+ taxonDescription = TaxonDescription.NewInstance();\r
+ taxonDescription.setTitleCache(sourceRef == null ? null:sourceRef.getTitleCache());\r
+ taxon.addDescription(taxonDescription);\r
+ }\r
+ }\r
+ \r
//textData\r
- TextData textData = TextData.NewInstance();\r
- //TODO textData.putText(fact, bmiConfig.getFactLanguage()); //doesn't work because bmiConfig.getFactLanguage() is not not a persistent Language Object\r
- //throws in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: eu.etaxonomy.cdm.model.common.Language; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: eu.etaxonomy.cdm.model.common.Language\r
+ TextData textData = null;\r
+ boolean newTextData = true;\r
+\r
+ // For Cichorieae DB: If fact category is 31 (Systematics) and there is already a Systematics TextData \r
+ // description element append the fact text to the existing TextData\r
+ if(categoryFk == 31) {\r
+ Set<DescriptionElementBase> descriptionElements = taxonDescription.getElements();\r
+ for (DescriptionElementBase descriptionElement : descriptionElements) {\r
+ String featureString = descriptionElement.getFeature().getRepresentation(Language.DEFAULT()).getLabel();\r
+ if (descriptionElement instanceof TextData && featureString.equals("Systematics")) { // TODO: test\r
+ textData = (TextData)descriptionElement;\r
+ String factTextStr = textData.getText(Language.DEFAULT());\r
+ // FIXME: Removing newlines doesn't work\r
+ if (factTextStr.contains("\\r\\n")) {\r
+ factTextStr = factTextStr.replaceAll("\\r\\n","");\r
+ }\r
+ StringBuilder factText = new StringBuilder(factTextStr);\r
+ factText.append(fact);\r
+ fact = factText.toString();\r
+ newTextData = false;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ if(newTextData == true) { textData = TextData.NewInstance(); }\r
+\r
+ \r
\r
//for diptera database\r
if (categoryFk == 99 && notes.contains("<OriginalName>")){\r
notes = notes.replaceAll("</OriginalName>", "");\r
fact = notes + ": " + fact ;\r
}\r
- textData.putText(fact, Language.DEFAULT());\r
- textData.setType(feature);\r
+ //TODO textData.putText(fact, bmiConfig.getFactLanguage()); //doesn't work because bmiConfig.getFactLanguage() is not not a persistent Language Object\r
+ //throws in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: eu.etaxonomy.cdm.model.common.Language; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: eu.etaxonomy.cdm.model.common.Language\r
+ if (isImage){\r
+ textData.addMedia(media);\r
+ textData.setType(Feature.IMAGE());\r
+ }else{\r
+ textData.putText(fact, Language.DEFAULT());\r
+ textData.setType(feature);\r
+ }\r
\r
//\r
ReferenceBase citation;\r
}\r
if (citation == null && (factRefFk != 0)){\r
logger.warn("Citation not found in referenceMap: " + factRefFk);\r
+ result = false;\r
}\r
}else{\r
citation = null;\r
}\r
\r
- \r
- textData.setCitation(citation);\r
- textData.setCitationMicroReference(details);\r
+ if (citation != null || CdmUtils.isNotEmpty(details)){\r
+ DescriptionElementSource originalSource = DescriptionElementSource.NewInstance();\r
+ originalSource.setCitation(citation);\r
+ originalSource.setCitationMicroReference(details);\r
+ textData.addSource(originalSource);\r
+ }\r
taxonDescription.addElement(textData);\r
+ //doubtfulFlag\r
+ if (doubtfulFlag){\r
+ textData.addMarker(Marker.NewInstance(MarkerType.IS_DOUBTFUL(), true));\r
+ }\r
+ //publisheFlag\r
+ textData.addMarker(Marker.NewInstance(MarkerType.PUBLISH(), publishFlag));\r
+ //Sequence\r
+ Integer sequence = rs.getInt("Sequence");\r
+ if (sequence != null && sequence != 999){\r
+ String strSequence = String.valueOf(sequence);\r
+ strSequence = SEQUENCE_PREFIX + strSequence;\r
+ //TODO make it an Extension when possible\r
+ //Extension datesExtension = Extension.NewInstance(textData, strSequence, ExtensionType.ORDER());\r
+ Annotation annotation = Annotation.NewInstance(strSequence, Language.DEFAULT());\r
+ textData.addAnnotation(annotation);\r
+ }\r
\r
- \r
-// if (categoryFkObj == FACT_DESCRIPTION){\r
+ // if (categoryFkObj == FACT_DESCRIPTION){\r
// //;\r
// }else if (categoryFkObj == FACT_OBSERVATION){\r
// //;\r
// //logger.warn("FactCategory " + categoryFk + " not yet implemented");\r
// }\r
\r
- //TODO\r
- //References\r
- //factId, \r
+ //notes\r
+ doCreatedUpdatedNotes(state, textData, rs, "Fact");\r
\r
- //etc.\r
- doCreatedUpdatedNotes(config, textData, rs, "Fact");\r
-\r
+ //TODO\r
+ //Designation References -> unclear how to map to CDM\r
+ //factId -> OriginalSource for descriptionElements not yet implemented\r
+ //sequence -> textData is not an identifiable entity therefore extensions are not possible\r
+ //fact category better\r
\r
taxonStore.add(taxon);\r
- }else{\r
- //TODO\r
- logger.warn("Taxon for Fact " + factId + " does not exist in store");\r
}\r
- } catch (RuntimeException re){\r
- logger.error("A runtime exception occurred during the facts import");\r
+ } catch (Exception re){\r
+ logger.error("An exception occurred during the facts import");\r
result = false;\r
- throw re;\r
}\r
//put\r
}\r
logger.info("Taxa to save: " + taxonStore.size());\r
getTaxonService().saveTaxonAll(taxonStore); \r
\r
- logger.info("end makeFacts ...");\r
+ logger.info("end makeFacts ..." + getSuccessString(result));\r
return result;\r
} catch (SQLException e) {\r
logger.error("SQLException:" + e);\r
\r
}\r
\r
+ /**\r
+ * @param state \r
+ * @param media \r
+ * @param media \r
+ * @param descriptionSet \r
+ * \r
+ */\r
+ private TaxonDescription makeImage(BerlinModelImportState state, String fact, Media media, Set<TaxonDescription> descriptionSet, Taxon taxon) {\r
+ TaxonDescription taxonDescription = null;\r
+ ReferenceBase sourceRef = state.getConfig().getSourceReference();\r
+ String uri = fact;\r
+ Integer size = null; \r
+ ImageMetaData imageMetaData = new ImageMetaData();\r
+ URL url;\r
+ try {\r
+ url = new URL(fact.trim());\r
+ } catch (MalformedURLException e) {\r
+ logger.warn("Malformed URL. Image could not be imported: " + CdmUtils.Nz(uri));\r
+ return null;\r
+ }\r
+ imageMetaData.readFrom(url);\r
+ MediaRepresentation mediaRepresentation = MediaRepresentation.NewInstance(imageMetaData.getMimeType(), null);\r
+ media.addRepresentation(mediaRepresentation);\r
+ ImageFile image = ImageFile.NewInstance(uri, size, imageMetaData);\r
+ mediaRepresentation.addRepresentationPart(image);\r
+ \r
+ taxonDescription = taxon.getOrCreateImageGallery(sourceRef == null ? null :sourceRef.getTitleCache());\r
+ \r
+ return taxonDescription;\r
+ }\r
+\r
+ private TaxonBase getTaxon(MapWrapper<TaxonBase> taxonMap, Object taxonIdObj, Integer taxonId){\r
+ if (taxonIdObj != null){\r
+ return taxonMap.get(taxonId);\r
+ }else{\r
+ return null;\r
+ }\r
+ \r
+ }\r
+ \r
+ private Feature getFeature(MapWrapper<Feature> featureMap, Object categoryFkObj, Integer categoryFk){\r
+ if (categoryFkObj != null){\r
+ return featureMap.get(categoryFk); \r
+ }else{\r
+ return null;\r
+ }\r
+ \r
+ }\r
+ \r
+ private boolean checkDesignationRefsExist(BerlinModelImportConfigurator config){\r
+ try {\r
+ boolean result = true;\r
+ Source source = config.getSource();\r
+ String strQueryArticlesWithoutJournal = "SELECT Count(*) as n " +\r
+ " FROM Fact " +\r
+ " WHERE (NOT (PTDesignationRefFk IS NULL) ) OR " +\r
+ " (NOT (PTDesignationRefDetailFk IS NULL) )";\r
+ ResultSet rs = source.getResultSet(strQueryArticlesWithoutJournal);\r
+ rs.next();\r
+ int count = rs.getInt("n");\r
+ if (count > 0){\r
+ System.out.println("========================================================");\r
+ logger.warn("There are "+count+" Facts with not empty designation references. Designation references are not imported.");\r
+ \r
+ System.out.println("========================================================");\r
+ }\r
+ return result;\r
+ } catch (SQLException e) {\r
+ e.printStackTrace();\r
+ return false;\r
+ }\r
+\r
+ }\r
+ \r
/* (non-Javadoc)\r
* @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)\r
*/\r
- protected boolean isIgnore(IImportConfigurator config){\r
- return ! config.isDoFacts();\r
+ protected boolean isIgnore(BerlinModelImportState state){\r
+ return ! state.getConfig().isDoFacts();\r
}\r
\r
}\r