2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.io
.common
;
12 import java
.net
.MalformedURLException
;
14 import java
.net
.URISyntaxException
;
15 import java
.sql
.ResultSet
;
16 import java
.sql
.SQLException
;
17 import java
.util
.HashSet
;
19 import java
.util
.UUID
;
21 import org
.apache
.log4j
.Logger
;
23 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
24 import eu
.etaxonomy
.cdm
.common
.mediaMetaData
.ImageMetaData
;
25 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
26 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.IInputTransformer
;
27 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.UndefinedTransformerMethodException
;
28 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
29 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
30 import eu
.etaxonomy
.cdm
.model
.common
.DescriptionElementSource
;
31 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
32 import eu
.etaxonomy
.cdm
.model
.common
.IOriginalSource
;
33 import eu
.etaxonomy
.cdm
.model
.common
.ISourceable
;
34 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
35 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
36 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
37 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
38 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
39 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
40 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
41 import eu
.etaxonomy
.cdm
.model
.description
.PresenceTerm
;
42 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
43 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
44 import eu
.etaxonomy
.cdm
.model
.location
.NamedAreaLevel
;
45 import eu
.etaxonomy
.cdm
.model
.location
.NamedAreaType
;
46 import eu
.etaxonomy
.cdm
.model
.media
.ImageFile
;
47 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
48 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
49 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
50 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
51 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
62 public abstract class CdmImportBase
<CONFIG
extends IImportConfigurator
, STATE
extends ImportStateBase
> extends CdmIoBase
<STATE
> implements ICdmImport
<CONFIG
, STATE
>{
63 private static Logger logger
= Logger
.getLogger(CdmImportBase
.class);
65 protected Classification
makeTree(STATE state
, Reference reference
){
66 Reference ref
= CdmBase
.deproxy(reference
, Reference
.class);
67 String treeName
= "Classification (Import)";
68 if (ref
!= null && CdmUtils
.isNotEmpty(ref
.getTitleCache())){
69 treeName
= ref
.getTitleCache();
71 Classification tree
= Classification
.NewInstance(treeName
);
72 tree
.setReference(ref
);
75 // use defined uuid for first tree
76 CONFIG config
= (CONFIG
)state
.getConfig();
77 if (state
.countTrees() < 1 ){
78 tree
.setUuid(config
.getClassificationUuid());
80 getClassificationService().save(tree
);
81 state
.putTree(ref
, tree
);
87 * Alternative memory saving method variant of
88 * {@link #makeTree(STATE state, Reference ref)} which stores only the
89 * UUID instead of the full tree in the <code>ImportStateBase</code> by
90 * using <code>state.putTreeUuid(ref, tree);</code>
96 protected Classification
makeTreeMemSave(STATE state
, Reference ref
){
97 String treeName
= "Classification (Import)";
98 if (ref
!= null && CdmUtils
.isNotEmpty(ref
.getTitleCache())){
99 treeName
= ref
.getTitleCache();
101 Classification tree
= Classification
.NewInstance(treeName
);
102 tree
.setReference(ref
);
105 // use defined uuid for first tree
106 CONFIG config
= (CONFIG
)state
.getConfig();
107 if (state
.countTrees() < 1 ){
108 tree
.setUuid(config
.getClassificationUuid());
110 getClassificationService().save(tree
);
111 state
.putTreeUuid(ref
, tree
);
116 protected ExtensionType
getExtensionType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
117 ExtensionType extensionType
= state
.getExtensionType(uuid
);
118 if (extensionType
== null){
119 extensionType
= (ExtensionType
)getTermService().find(uuid
);
120 if (extensionType
== null){
121 extensionType
= ExtensionType
.NewInstance(text
, label
, labelAbbrev
);
122 extensionType
.setUuid(uuid
);
123 UUID uuidExtensionTypeVoc
= UUID
.fromString("117cc307-5bd4-4b10-9b2f-2e14051b3b20");
124 TermVocabulary voc
= getVocabularyService().find(uuidExtensionTypeVoc
);
125 voc
.addTerm(extensionType
);
126 getTermService().save(extensionType
);
128 state
.putExtensionType(extensionType
);
130 return extensionType
;
134 protected MarkerType
getMarkerType(STATE state
, String keyString
) {
135 IInputTransformer transformer
= state
.getTransformer();
136 MarkerType markerType
= null;
138 markerType
= transformer
.getMarkerTypeByKey(keyString
);
139 } catch (UndefinedTransformerMethodException e
) {
140 logger
.info("getMarkerTypeByKey not yet implemented for this import");
142 if (markerType
== null ){
145 uuid
= transformer
.getMarkerTypeUuid(keyString
);
146 return getMarkerType(state
, uuid
, keyString
, keyString
, keyString
);
147 } catch (UndefinedTransformerMethodException e
) {
148 logger
.warn("getMarkerTypeUuid not yet implemented for this import");
154 protected MarkerType
getMarkerType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
155 MarkerType markerType
= state
.getMarkerType(uuid
);
156 if (markerType
== null){
157 markerType
= (MarkerType
)getTermService().find(uuid
);
158 if (markerType
== null){
159 markerType
= MarkerType
.NewInstance(label
, text
, labelAbbrev
);
160 markerType
.setUuid(uuid
);
161 UUID uuidMarkerTypeVoc
= UUID
.fromString("19dffff7-e142-429c-a420-5d28e4ebe305");
162 TermVocabulary voc
= getVocabularyService().find(uuidMarkerTypeVoc
);
163 voc
.addTerm(markerType
);
164 getTermService().save(markerType
);
166 state
.putMarkerType(markerType
);
171 protected AnnotationType
getAnnotationType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
172 AnnotationType annotationType
= state
.getAnnotationType(uuid
);
173 if (annotationType
== null){
174 annotationType
= (AnnotationType
)getTermService().find(uuid
);
175 if (annotationType
== null){
176 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
177 annotationType
.setUuid(uuid
);
178 UUID uuidAnnotationTypeVoc
= UUID
.fromString("ca04609b-1ba0-4d31-9c2e-aa8eb2f4e62d");
179 TermVocabulary voc
= getVocabularyService().find(uuidAnnotationTypeVoc
);
180 voc
.addTerm(annotationType
);
181 getTermService().save(annotationType
);
183 state
.putAnnotationType(annotationType
);
185 return annotationType
;
189 * Returns a named area for a given uuid by first . If the named area does not
199 protected NamedArea
getNamedArea(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, NamedAreaType areaType
, NamedAreaLevel level
){
200 NamedArea namedArea
= state
.getNamedArea(uuid
);
201 if (namedArea
== null){
202 namedArea
= (NamedArea
)getTermService().find(uuid
);
203 if (namedArea
== null){
204 namedArea
= NamedArea
.NewInstance(text
, label
, labelAbbrev
);
205 //FIXME define vocabulary
206 logger
.warn("No vocabulary defined for named area");
207 namedArea
.setType(areaType
);
208 namedArea
.setLevel(level
);
209 namedArea
.setUuid(uuid
);
210 getTermService().save(namedArea
);
212 state
.putNamedArea(namedArea
);
218 * Returns a feature for a given uuid by first ...
226 protected Feature
getFeature(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
230 Feature feature
= state
.getFeature(uuid
);
231 if (feature
== null){
232 feature
= (Feature
)getTermService().find(uuid
);
233 if (feature
== null){
234 feature
= Feature
.NewInstance(text
, label
, labelAbbrev
);
235 feature
.setUuid(uuid
);
236 feature
.setSupportsTextData(true);
237 //set vocabulary ; FIXME use another user-defined vocabulary
238 UUID uuidFeatureVoc
= UUID
.fromString("b187d555-f06f-4d65-9e53-da7c93f8eaa8");
239 TermVocabulary
<Feature
> voc
= getVocabularyService().find(uuidFeatureVoc
);
240 voc
.addTerm(feature
);
241 getTermService().save(feature
);
243 state
.putFeature(feature
);
249 * Returns a presence term for a given uuid by first ...
257 protected PresenceTerm
getPresenceTerm(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
261 PresenceTerm presenceTerm
= state
.getPresenceTerm(uuid
);
262 if (presenceTerm
== null){
263 presenceTerm
= (PresenceTerm
)getTermService().find(uuid
);
264 if (presenceTerm
== null){
265 presenceTerm
= PresenceTerm
.NewInstance(text
, label
, labelAbbrev
);
266 presenceTerm
.setUuid(uuid
);
267 //set vocabulary ; FIXME use another user-defined vocabulary
268 UUID uuidPresenceVoc
= UUID
.fromString("adbbbe15-c4d3-47b7-80a8-c7d104e53a05");
269 TermVocabulary
<PresenceTerm
> voc
= getVocabularyService().find(uuidPresenceVoc
);
270 voc
.addTerm(presenceTerm
);
271 getTermService().save(presenceTerm
);
273 state
.putPresenceTerm(presenceTerm
);
279 * Returns a language for a given uuid by first ...
287 protected Language
getLanguage(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
291 Language language
= state
.getLanguage(uuid
);
292 if (language
== null){
293 language
= (Language
)getTermService().find(uuid
);
294 if (language
== null){
295 language
= Language
.NewInstance(text
, label
, labelAbbrev
);
297 language
.setUuid(uuid
);
298 //set vocabulary ; FIXME use another user-defined vocabulary
299 UUID uuidLanguageVoc
= UUID
.fromString("45ac7043-7f5e-4f37-92f2-3874aaaef2de");
300 TermVocabulary
<Language
> voc
= getVocabularyService().find(uuidLanguageVoc
);
301 voc
.addTerm(language
);
302 getTermService().save(language
);
304 state
.putLanguage(language
);
310 * Adds an orginal source to a sourceable objects (implemented for Identifiable entity and description element.
311 * If cdmBase is not sourceable nothing happens.
312 * TODO Move to DbImportBase once this exists.
313 * TODO also implemented in DbImportObjectCreationMapper (reduce redundance)
316 * @param dbIdAttribute
319 * @throws SQLException
321 public void addOriginalSource(CdmBase cdmBase
, Object idAttributeValue
, String namespace
, Reference citation
) {
322 if (cdmBase
instanceof ISourceable
){
323 IOriginalSource source
;
324 ISourceable sourceable
= (ISourceable
)cdmBase
;
325 Object id
= idAttributeValue
;
326 String strId
= String
.valueOf(id
);
327 String microCitation
= null;
328 if (cdmBase
instanceof IdentifiableEntity
){
329 source
= IdentifiableSource
.NewInstance(strId
, namespace
, citation
, microCitation
);
330 }else if (cdmBase
instanceof DescriptionElementBase
){
331 source
= DescriptionElementSource
.NewInstance(strId
, namespace
, citation
, microCitation
);
333 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.");
336 sourceable
.addSource(source
);
337 }else if (cdmBase
!= null){
338 logger
.warn("Sourced object does not implement ISourceable: " + cdmBase
.getClass() + "," + cdmBase
.getUuid());
340 logger
.warn("Sourced object is null");
345 * @see #addOriginalSource(CdmBase, Object, String, Reference)
348 * @param dbIdAttribute
351 * @throws SQLException
353 public void addOriginalSource(ResultSet rs
, CdmBase cdmBase
, String dbIdAttribute
, String namespace
, Reference citation
) throws SQLException
{
354 Object id
= rs
.getObject(dbIdAttribute
);
355 addOriginalSource(cdmBase
, id
, namespace
, citation
);
360 * If the child taxon is missing genus or species epithet information and the rank is below <i>genus</i>
361 * or <i>species</i> respectively the according epithets are taken from the parent taxon.
362 * If the name is an autonym and has no combination author/basionym author the authors are taken from
367 protected void fillMissingEpithetsForTaxa(Taxon parentTaxon
, Taxon childTaxon
) {
368 NonViralName parentName
= HibernateProxyHelper
.deproxy(parentTaxon
.getName(), NonViralName
.class);
369 NonViralName childName
= HibernateProxyHelper
.deproxy(childTaxon
.getName(), NonViralName
.class);
370 fillMissingEpithets(parentName
, childName
);
374 * If the child name is missing genus or species epithet information and the rank is below <i>genus</i>
375 * or <i>species</i> respectively the according epithets are taken from the parent name.
376 * If the name is an autonym and has no combination author/basionym author the authors are taken from
381 protected void fillMissingEpithets(NonViralName parentName
, NonViralName childName
) {
382 if (CdmUtils
.isEmpty(childName
.getGenusOrUninomial()) && childName
.getRank().isLower(Rank
.GENUS()) ){
383 childName
.setGenusOrUninomial(parentName
.getGenusOrUninomial());
386 if (CdmUtils
.isEmpty(childName
.getSpecificEpithet()) && childName
.getRank().isLower(Rank
.SPECIES()) ){
387 childName
.setSpecificEpithet(parentName
.getSpecificEpithet());
389 if (childName
.isAutonym() && childName
.getCombinationAuthorTeam() == null && childName
.getBasionymAuthorTeam() == null ){
390 childName
.setCombinationAuthorTeam(parentName
.getCombinationAuthorTeam());
391 childName
.setBasionymAuthorTeam(parentName
.getBasionymAuthorTeam());
396 * Returns the image gallery for a taxon. If there are multiple taxon descriptions
397 * marked as image galleries an arbitrary one is chosen.
398 * If no image gallery exists, a new one is created if <code>createNewIfNotExists</code>
399 * is <code>true</code>.
400 * @param createNewIfNotExists
403 public TaxonDescription
getTaxonDescription(Taxon taxon
, boolean isImageGallery
, boolean createNewIfNotExists
) {
404 TaxonDescription result
= null;
405 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
406 for (TaxonDescription description
: descriptions
){
407 if (description
.isImageGallery() == isImageGallery
){
408 result
= description
;
412 if (result
== null && createNewIfNotExists
){
413 result
= TaxonDescription
.NewInstance(taxon
);
414 result
.setImageGallery(isImageGallery
);
421 * Returns the accepted taxon of a {@link TaxonBase taxon base}. <BR>
422 * If taxonBase is of type taxon the same object is returned. If taxonBase is of type
423 * synonym the accepted taxon is returned if one exists. If no accepted taxon exists
424 * <code>null</code> is returned. If multiple accepted taxa exist the one taxon with the
425 * same secundum reference is returned. If no such single taxon exists an
426 * {@link IllegalStateException illegal state exception} is thrown.
430 protected Taxon
getAcceptedTaxon(TaxonBase
<?
> taxonBase
) {
431 if (taxonBase
== null){
433 }else if(taxonBase
.isInstanceOf(Taxon
.class)){
434 return CdmBase
.deproxy(taxonBase
, Taxon
.class);
435 }else if(taxonBase
.isInstanceOf(Synonym
.class)){
436 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
437 Set
<Taxon
> acceptedTaxa
= synonym
.getAcceptedTaxa();
438 if (acceptedTaxa
.size() == 0){
440 }else if (acceptedTaxa
.size() == 1){
441 return acceptedTaxa
.iterator().next();
443 Reference sec
= synonym
.getSec();
445 Set
<Taxon
> taxaWithSameSec
= new HashSet
<Taxon
>();
446 for (Taxon taxon
: acceptedTaxa
){
447 if (sec
.equals(taxon
.getSec())){
448 taxaWithSameSec
.add(taxon
);
451 if (taxaWithSameSec
.size() == 1){
452 return taxaWithSameSec
.iterator().next();
455 throw new IllegalStateException("Can't define the one accepted taxon for a synonym out of multiple accept taxa");
458 throw new IllegalStateException("Unknown TaxonBase subclass: " + taxonBase
.getClass().getName());
465 * @param derivedUnitFacade
466 * @param multimediaObject
467 * @throws MalformedURLException
469 protected Media
getImageMedia(String multimediaObject
, boolean readDataFromUrl
) throws MalformedURLException
{
470 if( multimediaObject
== null){
473 ImageMetaData imd
= ImageMetaData
.newInstance();
476 uri
= new URI(multimediaObject
);
478 if (readDataFromUrl
){
479 imd
.readMetaData(uri
, 0);
481 } catch (Exception e
) {
482 String message
= "An error occurred when trying to read image meta data: " + e
.getMessage();
483 logger
.warn(message
);
485 ImageFile imf
= ImageFile
.NewInstance(uri
, null, imd
);
486 MediaRepresentation representation
= MediaRepresentation
.NewInstance();
487 representation
.setMimeType(imd
.getMimeType());
488 representation
.addRepresentationPart(imf
);
489 Media media
= Media
.NewInstance();
490 media
.addRepresentation(representation
);
492 } catch (URISyntaxException e1
) {
493 String message
= "An URISyntaxException occurred when trying to create uri from multimedia objcet string: " + multimediaObject
;
494 logger
.warn(message
);