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
.ArrayList
;
18 import java
.util
.Arrays
;
19 import java
.util
.HashSet
;
20 import java
.util
.List
;
22 import java
.util
.UUID
;
24 import org
.apache
.commons
.lang
.StringUtils
;
25 import org
.apache
.log4j
.Logger
;
27 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
28 import eu
.etaxonomy
.cdm
.common
.media
.ImageInfo
;
29 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
30 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.IInputTransformer
;
31 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.UndefinedTransformerMethodException
;
32 import eu
.etaxonomy
.cdm
.io
.markup
.MarkupTransformer
;
33 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
34 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
35 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTerm
;
36 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
37 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
38 import eu
.etaxonomy
.cdm
.model
.common
.IOriginalSource
;
39 import eu
.etaxonomy
.cdm
.model
.common
.ISourceable
;
40 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
41 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
42 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
43 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
44 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
45 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermVocabulary
;
46 import eu
.etaxonomy
.cdm
.model
.common
.OriginalSourceType
;
47 import eu
.etaxonomy
.cdm
.model
.common
.TermType
;
48 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
49 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
50 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
51 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementSource
;
52 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
53 import eu
.etaxonomy
.cdm
.model
.description
.MeasurementUnit
;
54 import eu
.etaxonomy
.cdm
.model
.description
.PresenceTerm
;
55 import eu
.etaxonomy
.cdm
.model
.description
.SpecimenDescription
;
56 import eu
.etaxonomy
.cdm
.model
.description
.State
;
57 import eu
.etaxonomy
.cdm
.model
.description
.StatisticalMeasure
;
58 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
59 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
60 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
61 import eu
.etaxonomy
.cdm
.model
.location
.Country
;
62 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
63 import eu
.etaxonomy
.cdm
.model
.location
.NamedAreaLevel
;
64 import eu
.etaxonomy
.cdm
.model
.location
.NamedAreaType
;
65 import eu
.etaxonomy
.cdm
.model
.location
.ReferenceSystem
;
66 import eu
.etaxonomy
.cdm
.model
.media
.ImageFile
;
67 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
68 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
69 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
70 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
71 import eu
.etaxonomy
.cdm
.model
.name
.RankClass
;
72 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
73 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
74 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
75 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
76 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
77 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
78 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
79 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
86 public abstract class CdmImportBase
<CONFIG
extends IImportConfigurator
, STATE
extends ImportStateBase
> extends CdmIoBase
<STATE
> implements ICdmImport
<CONFIG
, STATE
>{
87 private static Logger logger
= Logger
.getLogger(CdmImportBase
.class);
89 protected static final boolean CREATE
= true;
90 protected static final boolean IMAGE_GALLERY
= true;
91 protected static final boolean READ_MEDIA_DATA
= true;
93 public static final UUID uuidUserDefinedNamedAreaLevelVocabulary
= UUID
.fromString("255144da-8d95-457e-a327-9752a8f85e5a");
94 public static final UUID uuidUserDefinedNamedAreaVocabulary
= UUID
.fromString("b2238399-a3af-4f6d-b7eb-ff5d0899bf1b");
95 public static final UUID uuidUserDefinedExtensionTypeVocabulary
= UUID
.fromString("e28c1394-1be8-4847-8b81-ab44eb6d5bc8");
96 public static final UUID uuidUserDefinedReferenceSystemVocabulary
= UUID
.fromString("467591a3-10b4-4bf1-9239-f06ece33e90a");
97 public static final UUID uuidUserDefinedFeatureVocabulary
= UUID
.fromString("fe5fccb3-a2f2-4b97-b199-6e2743cf1627");
98 public static final UUID uuidUserDefinedMeasurementUnitVocabulary
= UUID
.fromString("d5e72bb7-f312-4080-bb86-c695d04a6e66");
99 public static final UUID uuidUserDefinedStatisticalMeasureVocabulary
= UUID
.fromString("62a89836-c730-4b4f-a904-3d859dbfc400");
100 public static final UUID uuidUserDefinedStateVocabulary
= UUID
.fromString("f7cddb49-8392-4db1-8640-65b48a0e6d13");
101 public static final UUID uuidUserDefinedTaxonRelationshipTypeVocabulary
= UUID
.fromString("31a324dc-408d-4877-891f-098db21744c6");
102 public static final UUID uuidUserDefinedAnnotationTypeVocabulary
= UUID
.fromString("cd9ecdd2-9cae-4890-9032-ad83293ae883");
103 public static final UUID uuidUserDefinedMarkerTypeVocabulary
= UUID
.fromString("5f02a261-fd7d-4fce-bbe4-21472de8cd51");
104 public static final UUID uuidUserDefinedRankVocabulary
= UUID
.fromString("4dc57931-38e2-46c3-974d-413b087646ba");
106 public static final UUID uuidUserDefinedModifierVocabulary
= UUID
.fromString("2a8b3838-3a95-49ea-9ab2-3049614b5884");
110 private static final String UuidOnly
= "UUIDOnly";
111 private static final String UuidLabel
= "UUID or label";
112 private static final String UuidLabelAbbrev
= "UUID, label or abbreviation";
113 private static final String UuidAbbrev
= "UUID or abbreviation";
115 public enum TermMatchMode
{
116 UUID_ONLY(0, UuidOnly
)
117 ,UUID_LABEL(1, UuidLabel
)
118 ,UUID_LABEL_ABBREVLABEL(2, UuidLabelAbbrev
)
119 ,UUID_ABBREVLABEL(3, UuidAbbrev
)
124 private String representation
;
125 private TermMatchMode(int id
, String representation
){
127 this.representation
= representation
;
132 public String
getRepresentation() {
133 return representation
;
135 public TermMatchMode
valueOf(int id
){
137 case 0: return UUID_ONLY
;
138 case 1: return UUID_LABEL
;
139 case 2: return UUID_LABEL_ABBREVLABEL
;
140 case 3: return UUID_ABBREVLABEL
;
141 default: return UUID_ONLY
;
148 protected Classification
makeTree(STATE state
, Reference
<?
> reference
){
149 String treeName
= "Classification (Import)";
150 if (reference
!= null && StringUtils
.isNotBlank(reference
.getTitleCache())){
151 treeName
= reference
.getTitleCache();
153 Classification tree
= Classification
.NewInstance(treeName
);
154 tree
.setReference(reference
);
157 // use defined uuid for first tree
158 CONFIG config
= (CONFIG
)state
.getConfig();
159 if (state
.countTrees() < 1 ){
160 tree
.setUuid(config
.getClassificationUuid());
162 getClassificationService().save(tree
);
163 state
.putTree(reference
, tree
);
169 * Alternative memory saving method variant of
170 * {@link #makeTree(STATE state, Reference ref)} which stores only the
171 * UUID instead of the full tree in the <code>ImportStateBase</code> by
172 * using <code>state.putTreeUuid(ref, tree);</code>
178 protected Classification
makeTreeMemSave(STATE state
, Reference ref
){
179 String treeName
= "Classification (Import)";
180 if (ref
!= null && StringUtils
.isNotBlank(ref
.getTitleCache())){
181 treeName
= ref
.getTitleCache();
183 Classification tree
= Classification
.NewInstance(treeName
);
184 tree
.setReference(ref
);
187 // use defined uuid for first tree
188 CONFIG config
= (CONFIG
)state
.getConfig();
189 if (state
.countTrees() < 1 ){
190 tree
.setUuid(config
.getClassificationUuid());
192 getClassificationService().save(tree
);
193 state
.putTreeUuid(ref
, tree
);
198 protected ExtensionType
getExtensionType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
199 return getExtensionType(state
, uuid
, label
, text
, labelAbbrev
, null);
201 protected ExtensionType
getExtensionType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, TermVocabulary
<ExtensionType
> voc
){
203 uuid
= UUID
.randomUUID();
205 ExtensionType extensionType
= state
.getExtensionType(uuid
);
206 if (extensionType
== null){
207 extensionType
= (ExtensionType
)getTermService().find(uuid
);
208 if (extensionType
== null){
209 extensionType
= ExtensionType
.NewInstance(text
, label
, labelAbbrev
);
210 extensionType
.setUuid(uuid
);
212 boolean isOrdered
= false;
213 voc
= getVocabulary(TermType
.ExtensionType
, uuidUserDefinedExtensionTypeVocabulary
, "User defined vocabulary for extension types", "User Defined Extension Types", null, null, isOrdered
, extensionType
);
215 voc
.addTerm(extensionType
);
216 getTermService().saveOrUpdate(extensionType
);
218 state
.putExtensionType(extensionType
);
220 return extensionType
;
224 protected MarkerType
getMarkerType(STATE state
, String keyString
) {
225 IInputTransformer transformer
= state
.getTransformer();
226 MarkerType markerType
= null;
228 markerType
= transformer
.getMarkerTypeByKey(keyString
);
229 } catch (UndefinedTransformerMethodException e
) {
230 logger
.info("getMarkerTypeByKey not yet implemented for this import");
232 if (markerType
== null ){
235 uuid
= transformer
.getMarkerTypeUuid(keyString
);
236 return getMarkerType(state
, uuid
, keyString
, keyString
, keyString
);
237 } catch (UndefinedTransformerMethodException e
) {
238 logger
.warn("getMarkerTypeUuid not yet implemented for this import");
244 protected MarkerType
getMarkerType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
245 return getMarkerType(state
, uuid
, label
, text
, labelAbbrev
, null);
249 protected MarkerType
getMarkerType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, TermVocabulary
<MarkerType
> voc
){
251 uuid
= UUID
.randomUUID();
253 MarkerType markerType
= state
.getMarkerType(uuid
);
254 if (markerType
== null){
255 markerType
= (MarkerType
)getTermService().find(uuid
);
256 if (markerType
== null){
257 markerType
= MarkerType
.NewInstance(label
, text
, labelAbbrev
);
258 markerType
.setUuid(uuid
);
260 boolean isOrdered
= false;
261 voc
= getVocabulary(TermType
.MarkerType
, uuidUserDefinedMarkerTypeVocabulary
, "User defined vocabulary for marker types", "User Defined Marker Types", null, null, isOrdered
, markerType
);
263 voc
.addTerm(markerType
);
264 getTermService().save(markerType
);
266 state
.putMarkerType(markerType
);
271 protected AnnotationType
getAnnotationType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, TermVocabulary
<AnnotationType
> voc
){
273 uuid
= UUID
.randomUUID();
275 AnnotationType annotationType
= state
.getAnnotationType(uuid
);
276 if (annotationType
== null){
277 annotationType
= (AnnotationType
)getTermService().find(uuid
);
278 if (annotationType
== null){
279 annotationType
= AnnotationType
.NewInstance(label
, text
, labelAbbrev
);
280 annotationType
.setUuid(uuid
);
282 boolean isOrdered
= false;
283 voc
= getVocabulary(TermType
.AnnotationType
, uuidUserDefinedAnnotationTypeVocabulary
, "User defined vocabulary for annotation types", "User Defined Annotation Types", null, null, isOrdered
, annotationType
);
286 voc
.addTerm(annotationType
);
287 getTermService().save(annotationType
);
289 state
.putAnnotationType(annotationType
);
291 return annotationType
;
295 protected ReferenceSystem
getReferenceSystem(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, TermVocabulary voc
){
297 uuid
= UUID
.randomUUID();
299 ReferenceSystem refSystem
= state
.getReferenceSystem(uuid
);
300 if (refSystem
== null){
301 refSystem
= (ReferenceSystem
)getTermService().find(uuid
);
302 if (refSystem
== null){
303 refSystem
= ReferenceSystem
.NewInstance(text
, label
, labelAbbrev
);
305 boolean isOrdered
= false;
306 voc
= getVocabulary(TermType
.ReferenceSystem
, uuidUserDefinedReferenceSystemVocabulary
, "User defined vocabulary for reference systems", "User Defined Reference System", null, null, isOrdered
, refSystem
);
308 voc
.addTerm(refSystem
);
309 refSystem
.setUuid(uuid
);
310 getTermService().save(refSystem
);
312 state
.putReferenceSystem(refSystem
);
320 protected Rank
getRank(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
,OrderedTermVocabulary
<Rank
> voc
, Rank lowerRank
, RankClass rankClass
){
322 uuid
= UUID
.randomUUID();
324 Rank rank
= state
.getRank(uuid
);
326 rank
= (Rank
)getTermService().find(uuid
);
328 rank
= Rank
.NewInstance(rankClass
, text
, label
, labelAbbrev
);
330 boolean isOrdered
= true;
331 voc
= (OrderedTermVocabulary
)getVocabulary(TermType
.Rank
, uuidUserDefinedRankVocabulary
, "User defined vocabulary for ranks", "User Defined Reference System", null, null, isOrdered
, rank
);
333 if (lowerRank
== null){
336 voc
.addTermAbove(rank
, lowerRank
);
339 getTermService().save(rank
);
348 * Returns a named area for a given uuid by first . If the named area does not
358 protected NamedArea
getNamedArea(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, NamedAreaType areaType
, NamedAreaLevel level
){
359 return getNamedArea(state
, uuid
, label
, text
, labelAbbrev
, areaType
, level
, null, null);
362 protected NamedArea
getNamedArea(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, NamedAreaType areaType
, NamedAreaLevel level
, TermVocabulary voc
, TermMatchMode matchMode
){
363 return getNamedArea(state
, uuid
, label
, text
, labelAbbrev
, areaType
, level
, voc
, matchMode
, null);
367 protected NamedArea
getNamedArea(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, NamedAreaType areaType
, NamedAreaLevel level
, TermVocabulary voc
, TermMatchMode matchMode
,
368 List
<TermVocabulary
<NamedArea
>> vocabularyPreference
){
369 Class
<NamedArea
> clazz
= NamedArea
.class;
371 uuid
= UUID
.randomUUID();
373 if (matchMode
== null){
374 matchMode
= TermMatchMode
.UUID_ONLY
;
376 NamedArea namedArea
= state
.getNamedArea(uuid
);
377 if (namedArea
== null){
378 DefinedTermBase
<?
> term
= getTermService().find(uuid
);
379 namedArea
= CdmBase
.deproxy(term
,NamedArea
.class);
381 if (vocabularyPreference
== null){
382 vocabularyPreference
= new ArrayList
<TermVocabulary
<NamedArea
>>();
384 if (vocabularyPreference
.isEmpty()){
385 vocabularyPreference
.add(Country
.GERMANY().getVocabulary());
386 vocabularyPreference
.add(TdwgAreaProvider
.getAreaByTdwgAbbreviation("GER").getVocabulary());
390 //TODO matching still experimental
391 if (namedArea
== null && (matchMode
.equals(TermMatchMode
.UUID_LABEL
) || matchMode
.equals(TermMatchMode
.UUID_LABEL_ABBREVLABEL
))){
393 Pager
<NamedArea
> areaPager
= (Pager
)getTermService().findByTitle(clazz
, label
, null, null, null, null, null, null);
394 namedArea
= findBestMatchingArea(areaPager
, uuid
, label
, text
, labelAbbrev
, vocabularyPreference
);
396 if (namedArea
== null && (matchMode
.equals(TermMatchMode
.UUID_ABBREVLABEL
) || matchMode
.equals(TermMatchMode
.UUID_LABEL_ABBREVLABEL
))){
397 Pager
<NamedArea
> areaPager
= getTermService().findByRepresentationAbbreviation(labelAbbrev
, clazz
, null, null);
398 namedArea
= findBestMatchingArea(areaPager
, uuid
, label
, text
, labelAbbrev
, vocabularyPreference
);
401 if (namedArea
== null){
402 namedArea
= NamedArea
.NewInstance(text
, label
, labelAbbrev
);
404 boolean isOrdered
= true;
405 voc
= getVocabulary(TermType
.NamedArea
, uuidUserDefinedNamedAreaVocabulary
, "User defined vocabulary for named areas", "User Defined Named Areas", null, null, isOrdered
, namedArea
);
407 voc
.addTerm(namedArea
);
408 namedArea
.setType(areaType
);
409 namedArea
.setLevel(level
);
410 namedArea
.setUuid(uuid
);
411 getTermService().saveOrUpdate(namedArea
);
413 state
.putNamedArea(namedArea
);
419 private NamedArea
findBestMatchingArea(Pager
<NamedArea
> areaPager
, UUID uuid
, String label
, String text
, String abbrev
, List
<TermVocabulary
<NamedArea
>> vocabularyPreference
) {
420 // TODO preliminary implementation
421 List
<NamedArea
> list
= areaPager
.getRecords();
422 if (list
.size() == 0){
424 }else if (list
.size() == 1){
426 }else if (list
.size() > 1){
427 List
<NamedArea
> preferredList
= new ArrayList
<NamedArea
>();
428 for (TermVocabulary
<NamedArea
> voc
: vocabularyPreference
){
429 for (NamedArea area
: list
){
430 if (voc
.equals(area
.getVocabulary())){
431 preferredList
.add(area
);
434 if (preferredList
.size() > 0){
438 if (preferredList
.size() > 1 ){
439 preferredList
= getLowestLevelAreas(preferredList
);
440 }else if (preferredList
.size() == 0 ){
441 preferredList
= list
;
443 if (preferredList
.size() == 1 ){
444 return preferredList
.get(0);
445 }else if (preferredList
.size() > 1 ){
446 String message
= "There is more than 1 matching area for %s, %s, %s. As a preliminary implementation I take the first";
447 message
= String
.format(message
, label
, abbrev
, text
);
448 logger
.warn(message
);
456 private List
<NamedArea
> getLowestLevelAreas(List
<NamedArea
> preferredList
) {
457 List
<NamedArea
> result
= new ArrayList
<NamedArea
>();
458 for (NamedArea area
: preferredList
){
459 if (result
.isEmpty()){
462 int compare
= compareAreaLevel(area
, result
.get(0));
464 result
= new ArrayList
<NamedArea
>();
466 }else if (compare
== 0){
479 private int compareAreaLevel(NamedArea area1
, NamedArea area2
) {
480 NamedAreaLevel level1
= area1
.getLevel();
481 NamedAreaLevel level2
= area2
.getLevel();
483 return (level2
== null)?
0 : 1;
484 }else if (level2
== null){
487 return level1
.compareTo(level2
);
492 protected NamedAreaLevel
getNamedAreaLevel(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, TermVocabulary
<NamedAreaLevel
> voc
){
494 uuid
= UUID
.randomUUID();
496 NamedAreaLevel namedAreaLevel
= state
.getNamedAreaLevel(uuid
);
497 if (namedAreaLevel
== null){
498 //TODO propPath just for testing
499 List
<String
> propPath
= Arrays
.asList("vocabulary");
500 DefinedTermBase
<NamedAreaLevel
> term
= getTermService().load(uuid
, propPath
);
501 namedAreaLevel
= CdmBase
.deproxy(term
, NamedAreaLevel
.class);
502 if (namedAreaLevel
== null){
503 namedAreaLevel
= NamedAreaLevel
.NewInstance(text
, label
, labelAbbrev
);
505 boolean isOrdered
= true;
506 voc
= getVocabulary(TermType
.NamedAreaLevel
, uuidUserDefinedNamedAreaLevelVocabulary
, "User defined vocabulary for named area levels", "User Defined Named Area Levels", null, null, isOrdered
, namedAreaLevel
);
508 //FIXME only for debugging
509 Set
<NamedAreaLevel
> terms
= voc
.getTerms();
510 for (NamedAreaLevel level
: terms
){
511 TermVocabulary
<NamedAreaLevel
> levelVoc
= level
.getVocabulary();
512 if (levelVoc
== null){
513 logger
.error("ONLY FOR DEBUG: Level voc is null");
515 logger
.info("ONLY FOR DEBUG: Level voc is not null");
518 voc
.addTerm(namedAreaLevel
);
519 namedAreaLevel
.setUuid(uuid
);
520 getTermService().save(namedAreaLevel
);
522 state
.putNamedAreaLevel(namedAreaLevel
);
524 return namedAreaLevel
;
528 * Returns a {@link State} if it exists. <code>null</code> otherwise.
531 * @return {@link State}
533 protected State
getStateTerm(STATE state
, UUID uuid
){
534 return getStateTerm(state
, uuid
, null, null, null, null);
539 * Returns a {@link State} for a given uuid by first checking if the uuid has already been used in this import, if not
540 * checking if the state exists in the database, if not creating it anew (with vocabulary etc.).
541 * If label, text and labelAbbrev are all <code>null</code> no state is created.
550 protected State
getStateTerm(STATE importState
, UUID uuid
, String label
, String text
, String labelAbbrev
, OrderedTermVocabulary
<State
> voc
) {
554 State stateTerm
= importState
.getStateTerm(uuid
);
555 if (stateTerm
== null){
556 stateTerm
= CdmBase
.deproxy(getTermService().find(uuid
), State
.class);
557 if (stateTerm
== null && ! hasNoLabel(label
, text
, labelAbbrev
)){
558 stateTerm
= State
.NewInstance(text
, label
, labelAbbrev
);
559 stateTerm
.setUuid(uuid
);
561 boolean isOrdered
= true;
562 TermVocabulary
<State
> orderedVoc
= getVocabulary(TermType
.State
, uuidUserDefinedStateVocabulary
, "User defined vocabulary for states used by Categorical Data", "User Defined States", null, null, isOrdered
, stateTerm
);
563 voc
= CdmBase
.deproxy(orderedVoc
, OrderedTermVocabulary
.class);
565 voc
.addTerm(stateTerm
);
566 getTermService().save(stateTerm
);
568 logger
.warn("No label provided for new state with uuid " + uuid
);
570 importState
.putStateTerm(stateTerm
);
576 * Returns a feature if it exists, null otherwise.
577 * @see #getFeature(ImportStateBase, UUID, String, String, String, TermVocabulary)
582 protected Feature
getFeature(STATE state
, UUID uuid
){
583 return getFeature(state
, uuid
, null, null, null, null);
587 * Returns a feature for a given uuid by first checking if the uuid has already been used in this import, if not
588 * checking if the feature exists in the database, if not creating it anew (with vocabulary etc.).
589 * If label, text and labelAbbrev are all <code>null</code> no feature is created.
597 protected Feature
getFeature(STATE state
, UUID uuid
, String label
, String description
, String labelAbbrev
, TermVocabulary
<Feature
> voc
){
601 Feature feature
= state
.getFeature(uuid
);
602 if (feature
== null){
603 feature
= (Feature
)getTermService().find(uuid
);
604 if (feature
== null && ! hasNoLabel(label
, description
, labelAbbrev
)){
605 feature
= Feature
.NewInstance(description
, label
, labelAbbrev
);
606 feature
.setUuid(uuid
);
607 feature
.setSupportsTextData(true);
608 // UUID uuidFeatureVoc = UUID.fromString("b187d555-f06f-4d65-9e53-da7c93f8eaa8");
610 boolean isOrdered
= false;
611 voc
= getVocabulary(TermType
.Feature
, uuidUserDefinedFeatureVocabulary
, "User defined vocabulary for features", "User Defined Features", null, null, isOrdered
, feature
);
613 voc
.addTerm(feature
);
614 getTermService().save(feature
);
616 state
.putFeature(feature
);
622 * Returns a {@link MeasurementUnit} for a given uuid by first checking if the uuid has already been used in this import, if not
623 * checking if the {@link MeasurementUnit} exists in the database, if not creating it anew (with vocabulary etc.).
624 * If label, text and labelAbbrev are all <code>null</code> no {@link MeasurementUnit} is created.
632 protected MeasurementUnit
getMeasurementUnit(STATE state
, UUID uuid
, String label
, String description
, String labelAbbrev
, TermVocabulary
<MeasurementUnit
> voc
){
636 MeasurementUnit unit
= state
.getMeasurementUnit(uuid
);
638 unit
= (MeasurementUnit
)getTermService().find(uuid
);
639 if (unit
== null && ! hasNoLabel(label
, description
, labelAbbrev
)){
640 unit
= MeasurementUnit
.NewInstance(description
, label
, labelAbbrev
);
643 boolean isOrdered
= false;
644 voc
= getVocabulary(TermType
.MeasurementUnit
, uuidUserDefinedMeasurementUnitVocabulary
, "User defined vocabulary for measurement units", "User Defined Measurement Units", null, null, isOrdered
, unit
);
647 getTermService().save(unit
);
649 state
.putMeasurementUnit(unit
);
655 * Returns a {@link StatisticalMeasure} for a given uuid by first checking if the uuid has already been used in this import, if not
656 * checking if the {@link StatisticalMeasure} exists in the database, if not creating it anew (with vocabulary etc.).
657 * If label, text and labelAbbrev are all <code>null</code> no {@link StatisticalMeasure} is created.
665 protected StatisticalMeasure
getStatisticalMeasure(STATE state
, UUID uuid
, String label
, String description
, String labelAbbrev
, TermVocabulary
<StatisticalMeasure
> voc
){
669 StatisticalMeasure statisticalMeasure
= state
.getStatisticalMeasure(uuid
);
670 if (statisticalMeasure
== null){
671 statisticalMeasure
= (StatisticalMeasure
)getTermService().find(uuid
);
672 if (statisticalMeasure
== null && ! hasNoLabel(label
, description
, labelAbbrev
)){
673 statisticalMeasure
= StatisticalMeasure
.NewInstance(description
, label
, labelAbbrev
);
674 statisticalMeasure
.setUuid(uuid
);
676 boolean isOrdered
= false;
677 voc
= getVocabulary(TermType
.StatisticalMeasure
, uuidUserDefinedStatisticalMeasureVocabulary
, "User defined vocabulary for statistical measures", "User Defined Statistical Measures", null, null, isOrdered
, statisticalMeasure
);
679 voc
.addTerm(statisticalMeasure
);
680 getTermService().save(statisticalMeasure
);
682 state
.putStatisticalMeasure(statisticalMeasure
);
684 return statisticalMeasure
;
688 * Returns a {@link Modifier} for a given uuid by first checking if the uuid has already been used in this import, if not
689 * checking if the {@link Modifier} exists in the database, if not creating it anew (with vocabulary etc.).
690 * If label, text and labelAbbrev are all <code>null</code> no {@link Modifier} is created.
698 protected DefinedTerm
getModifier(STATE state
, UUID uuid
, String label
, String description
, String labelAbbrev
, TermVocabulary
<DefinedTerm
> voc
){
702 DefinedTerm modifier
= state
.getModifier(uuid
);
703 if (modifier
== null){
704 modifier
= (DefinedTerm
)getTermService().find(uuid
);
705 if (modifier
== null && ! hasNoLabel(label
, description
, labelAbbrev
)){
706 modifier
= DefinedTerm
.NewModifierInstance(description
, label
, labelAbbrev
);
707 modifier
.setUuid(uuid
);
709 boolean isOrdered
= false;
710 voc
= getVocabulary(TermType
.Modifier
, uuidUserDefinedModifierVocabulary
, "User defined vocabulary for modifier", "User Defined Modifier", null, null, isOrdered
, modifier
);
712 voc
.addTerm(modifier
);
713 getTermService().save(modifier
);
715 state
.putModifier(modifier
);
721 * Returns a taxon relationship type for a given uuid by first checking if the uuid has already been used in this import, if not
722 * checking if the taxon relationship type exists in the database, if not creating it anew (with vocabulary etc.).
723 * If label, text and labelAbbrev are all <code>null</code> no taxon relationship type is created.
731 protected TaxonRelationshipType
getTaxonRelationshipType(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, TermVocabulary
<TaxonRelationshipType
> voc
){
735 TaxonRelationshipType relType
= state
.getTaxonRelationshipType(uuid
);
736 if (relType
== null){
737 relType
= (TaxonRelationshipType
)getTermService().find(uuid
);
738 if (relType
== null && ! hasNoLabel(label
, text
, labelAbbrev
)){
739 relType
= TaxonRelationshipType
.NewInstance(text
, label
, labelAbbrev
, false, false);
740 relType
.setUuid(uuid
);
742 boolean isOrdered
= true;
743 voc
= getVocabulary(TermType
.TaxonRelationshipType
, uuidUserDefinedTaxonRelationshipTypeVocabulary
, "User defined vocabulary for taxon relationship types", "User Defined Taxon Relationship Types", null, null, isOrdered
, relType
);
745 voc
.addTerm(relType
);
746 getTermService().save(relType
);
748 state
.putTaxonRelationshipType(relType
);
753 private boolean hasNoLabel(String label
, String text
, String labelAbbrev
) {
754 return label
== null && text
== null && labelAbbrev
== null;
759 * Returns a presence term for a given uuid by first ...
767 protected PresenceTerm
getPresenceTerm(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
771 PresenceTerm presenceTerm
= state
.getPresenceTerm(uuid
);
772 if (presenceTerm
== null){
773 presenceTerm
= (PresenceTerm
)getTermService().find(uuid
);
774 if (presenceTerm
== null){
775 presenceTerm
= PresenceTerm
.NewInstance(text
, label
, labelAbbrev
);
776 presenceTerm
.setUuid(uuid
);
777 //set vocabulary ; FIXME use another user-defined vocabulary
778 UUID uuidPresenceVoc
= UUID
.fromString("adbbbe15-c4d3-47b7-80a8-c7d104e53a05");
779 TermVocabulary
<PresenceTerm
> voc
= getVocabularyService().find(uuidPresenceVoc
);
780 voc
.addTerm(presenceTerm
);
781 getTermService().save(presenceTerm
);
783 state
.putPresenceTerm(presenceTerm
);
789 * Returns a language for a given uuid by first ...
797 protected Language
getLanguage(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
){
798 return getLanguage(state
, uuid
, label
, text
, labelAbbrev
, null);
801 protected Language
getLanguage(STATE state
, UUID uuid
, String label
, String text
, String labelAbbrev
, TermVocabulary voc
){
805 Language language
= state
.getLanguage(uuid
);
806 if (language
== null){
807 language
= (Language
)getTermService().find(uuid
);
808 if (language
== null){
809 language
= Language
.NewInstance(text
, label
, labelAbbrev
);
811 language
.setUuid(uuid
);
813 UUID uuidLanguageVoc
= UUID
.fromString("463a96f1-20ba-4a4c-9133-854c1682bd9b");
814 boolean isOrdered
= false;
815 voc
= getVocabulary(TermType
.Language
, uuidLanguageVoc
, "User defined languages", "User defined languages", "User defined languages", null, isOrdered
, language
);
817 //set vocabulary ; FIXME use another user-defined vocabulary
819 voc
.addTerm(language
);
820 getTermService().save(language
);
822 state
.putLanguage(language
);
833 protected <T
extends DefinedTermBase
> TermVocabulary
<T
> getVocabulary(TermType termType
, UUID uuid
, String description
, String label
, String abbrev
, URI termSourceUri
, boolean isOrdered
, T type
) {
834 List
<String
> propPath
= Arrays
.asList(new String
[]{"terms"});
835 TermVocabulary
<T
> voc
= getVocabularyService().load(uuid
, propPath
);
838 voc
= OrderedTermVocabulary
.NewInstance(termType
, description
, label
, abbrev
, termSourceUri
);
840 voc
= TermVocabulary
.NewInstance(termType
, description
, label
, abbrev
, termSourceUri
);
843 getVocabularyService().save(voc
);
849 * Adds an orginal source to a sourceable objects (implemented for Identifiable entity and description element.
850 * If cdmBase is not sourceable nothing happens.
851 * TODO Move to DbImportBase once this exists.
852 * TODO also implemented in DbImportObjectCreationMapper (reduce redundance)
855 * @param dbIdAttribute
858 * @throws SQLException
860 public void addOriginalSource(CdmBase cdmBase
, Object idAttributeValue
, String namespace
, Reference citation
) {
861 if (cdmBase
instanceof ISourceable
){
862 IOriginalSource source
;
863 ISourceable sourceable
= (ISourceable
<?
>)cdmBase
;
864 Object id
= idAttributeValue
;
865 String strId
= String
.valueOf(id
);
866 String microCitation
= null;
867 OriginalSourceType type
= OriginalSourceType
.Import
;
868 if (cdmBase
instanceof IdentifiableEntity
){
869 source
= IdentifiableSource
.NewInstance(type
, strId
, namespace
, citation
, microCitation
);
870 }else if (cdmBase
instanceof DescriptionElementBase
){
871 source
= DescriptionElementSource
.NewInstance(type
, strId
, namespace
, citation
, microCitation
);
873 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.");
876 sourceable
.addSource(source
);
877 }else if (cdmBase
!= null){
878 logger
.warn("Sourced object does not implement ISourceable: " + cdmBase
.getClass() + "," + cdmBase
.getUuid());
880 logger
.warn("Sourced object is null");
885 * @see #addOriginalSource(CdmBase, Object, String, Reference)
888 * @param dbIdAttribute
891 * @throws SQLException
893 public void addOriginalSource(ResultSet rs
, CdmBase cdmBase
, String dbIdAttribute
, String namespace
, Reference citation
) throws SQLException
{
894 Object id
= rs
.getObject(dbIdAttribute
);
895 addOriginalSource(cdmBase
, id
, namespace
, citation
);
900 * If the child taxon is missing genus or species epithet information and the rank is below <i>genus</i>
901 * or <i>species</i> respectively the according epithets are taken from the parent taxon.
902 * If the name is an autonym and has no combination author/basionym author the authors are taken from
907 protected void fillMissingEpithetsForTaxa(Taxon parentTaxon
, Taxon childTaxon
) {
908 if (parentTaxon
== null){
909 logger
.warn("Parent taxon is null. Missing name parts can not be taken from parent");
912 NonViralName
<?
> parentName
= HibernateProxyHelper
.deproxy(parentTaxon
.getName(), NonViralName
.class);
913 NonViralName
<?
> childName
= HibernateProxyHelper
.deproxy(childTaxon
.getName(), NonViralName
.class);
914 fillMissingEpithets(parentName
, childName
);
918 * If the child name is missing genus or species epithet information and the rank is below <i>genus</i>
919 * or <i>species</i> respectively the according epithets are taken from the parent name.
920 * If the name is an autonym and has no combination author/basionym author the authors are taken from
925 protected void fillMissingEpithets(NonViralName parentName
, NonViralName childName
) {
926 if (StringUtils
.isBlank(childName
.getGenusOrUninomial()) && childName
.getRank().isLower(Rank
.GENUS()) ){
927 childName
.setGenusOrUninomial(parentName
.getGenusOrUninomial());
930 if (StringUtils
.isBlank(childName
.getSpecificEpithet()) && childName
.getRank().isLower(Rank
.SPECIES()) ){
931 childName
.setSpecificEpithet(parentName
.getSpecificEpithet());
933 if (childName
.isAutonym() && childName
.getCombinationAuthorTeam() == null && childName
.getBasionymAuthorTeam() == null ){
934 childName
.setCombinationAuthorTeam(parentName
.getCombinationAuthorTeam());
935 childName
.setBasionymAuthorTeam(parentName
.getBasionymAuthorTeam());
940 * Returns the taxon description for a taxon. If there are multiple taxon descriptions
941 * an arbitrary one is chosen.
942 * If no taxon description exists, a new one is created if <code>createNewIfNotExists</code>
943 * is <code>true</code>.
944 * @param createNewIfNotExists
945 * @param isImageGallery if true only taxon description being image galleries are considered.
946 * If false only taxon description being no image galleries are considered.
949 public TaxonNameDescription
getTaxonNameDescription(TaxonNameBase name
, boolean isImageGallery
, boolean createNewIfNotExists
) {
950 Reference
<?
> ref
= null;
951 return getTaxonNameDescription(name
, ref
, isImageGallery
, createNewIfNotExists
);
955 * Like {@link #getTaxonDescription(Taxon, boolean, boolean)}
956 * Only matches a description if the given reference is a source of the description.<BR>
957 * If a new description is created the given reference will be added as a source.
959 * @see #getTaxonDescription(Taxon, boolean, boolean)
961 public TaxonNameDescription
getTaxonNameDescription(TaxonNameBase
<?
,?
> name
, Reference ref
, boolean isImageGallery
, boolean createNewIfNotExists
) {
962 TaxonNameDescription result
= null;
963 Set
<TaxonNameDescription
> descriptions
= name
.getDescriptions();
964 for (TaxonNameDescription description
: descriptions
){
965 if (description
.isImageGallery() == isImageGallery
){
966 if (hasCorrespondingSource(ref
, description
)){
967 result
= description
;
972 if (result
== null && createNewIfNotExists
){
973 result
= TaxonNameDescription
.NewInstance(name
);
974 result
.setImageGallery(isImageGallery
);
976 result
.addImportSource(null, null, ref
, null);
983 * Returns the taxon description for a taxon. If there are multiple taxon descriptions
984 * an arbitrary one is chosen.
985 * If no taxon description exists, a new one is created if <code>createNewIfNotExists</code>
986 * is <code>true</code>.
987 * @param createNewIfNotExists
988 * @param isImageGallery if true only taxon description being image galleries are considered.
989 * If false only taxon description being no image galleries are considered.
992 public TaxonDescription
getTaxonDescription(Taxon taxon
, boolean isImageGallery
, boolean createNewIfNotExists
) {
993 Reference
<?
> ref
= null;
994 return getTaxonDescription(taxon
, ref
, isImageGallery
, createNewIfNotExists
);
998 * Like {@link #getTaxonDescription(Taxon, boolean, boolean)}
999 * Only matches a description if the given reference is a source of the description.<BR>
1000 * If a new description is created the given reference will be added as a source.
1002 * @see #getTaxonDescription(Taxon, boolean, boolean)
1004 public TaxonDescription
getTaxonDescription(Taxon taxon
, Reference ref
, boolean isImageGallery
, boolean createNewIfNotExists
) {
1005 TaxonDescription result
= null;
1006 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
1007 for (TaxonDescription description
: descriptions
){
1008 if (description
.isImageGallery() == isImageGallery
){
1009 if (hasCorrespondingSource(ref
, description
)){
1010 result
= description
;
1015 if (result
== null && createNewIfNotExists
){
1016 result
= TaxonDescription
.NewInstance(taxon
);
1017 result
.setImageGallery(isImageGallery
);
1019 result
.addImportSource(null, null, ref
, null);
1027 * Returns the {@link SpecimenDescription specimen description} for a {@link SpecimenOrObservationBase specimen or observation}.
1028 * If there are multiple specimen descriptions an arbitrary one is chosen.
1029 * If no specimen description exists, a new one is created if <code>createNewIfNotExists</code> is <code>true</code>.
1030 * @param createNewIfNotExists
1031 * @param isImageGallery if true only specimen description being image galleries are considered.
1032 * If false only specimen description being no image galleries are considered.
1035 public SpecimenDescription
getSpecimenDescription(SpecimenOrObservationBase specimen
, boolean isImageGallery
, boolean createNewIfNotExists
) {
1036 Reference ref
= null;
1037 return getSpecimenDescription(specimen
, ref
, isImageGallery
, createNewIfNotExists
);
1041 * Like {@link #getSpecimenDescription(SpecimenOrObservationBase, boolean, boolean)}
1042 * Only matches a description if the given reference is a source of the description.<BR>
1043 * If a new description is created the given reference will be added as a source.
1045 * @see #getTaxonDescription(Taxon, boolean, boolean)
1047 public SpecimenDescription
getSpecimenDescription(SpecimenOrObservationBase specimen
, Reference ref
, boolean isImageGallery
, boolean createNewIfNotExists
) {
1048 SpecimenDescription result
= null;
1049 Set
<SpecimenDescription
> descriptions
= specimen
.getDescriptions();
1050 for (SpecimenDescription description
: descriptions
){
1051 if (description
.isImageGallery() == isImageGallery
){
1052 if (hasCorrespondingSource(ref
, description
)){
1053 result
= description
;
1058 if (result
== null && createNewIfNotExists
){
1059 result
= SpecimenDescription
.NewInstance(specimen
);
1060 result
.setImageGallery(isImageGallery
);
1062 result
.addImportSource(null, null, ref
, null);
1070 * Returns the textdata that holds general information about a feature for a taxon description.
1071 * This is mainly necessary for descriptions that have more than one description element for
1072 * a given feature such as 'distribution', 'description' or 'common name'. It may also hold
1073 * for hierarchical features where no description element exists for a higher hierarchy level.
1074 * Example: the description feature has subfeatures. But some information like authorship, figures,
1075 * sources need to be added to the description itself.
1076 * Currently a feature placeholder is marked by a marker of type 'feature placeholder'. Maybe in future
1077 * there will be a boolean marker in the TextData class itself.
1082 * @param createIfNotExists
1085 protected TextData
getFeaturePlaceholder(STATE state
, DescriptionBase
<?
> description
, Feature feature
, boolean createIfNotExists
) {
1086 UUID featurePlaceholderUuid
= MarkupTransformer
.uuidFeaturePlaceholder
;
1087 for (DescriptionElementBase element
: description
.getElements()){
1088 if (element
.isInstanceOf(TextData
.class)){
1089 TextData textData
= CdmBase
.deproxy(element
, TextData
.class);
1090 if (textData
.getFeature() == null || ! textData
.getFeature().equals(feature
)){
1093 for (Marker marker
: textData
.getMarkers()){
1094 MarkerType markerType
= marker
.getMarkerType();
1095 if (markerType
!= null &&
1096 markerType
.getUuid().equals(featurePlaceholderUuid
) &&
1097 marker
.getValue() == true){
1103 if (createIfNotExists
){
1104 TextData newPlaceholder
= TextData
.NewInstance(feature
);
1105 MarkerType placeholderMarkerType
= getMarkerType(state
, featurePlaceholderUuid
, "Feature Placeholder", "Feature Placeholder", null);
1106 Marker marker
= Marker
.NewInstance(placeholderMarkerType
, true);
1107 newPlaceholder
.addMarker(marker
);
1108 description
.addElement(newPlaceholder
);
1109 return newPlaceholder
;
1118 * Returns true, if this description has a source with a citation equal to the given reference.
1119 * Returns true if the given reference is null.
1121 * @param description
1123 private boolean hasCorrespondingSource(Reference
<?
> ref
, DescriptionBase
<?
> description
) {
1125 for (IdentifiableSource source
: description
.getSources()){
1126 if (ref
.equals(source
.getCitation())){
1138 * Returns the accepted taxon of a {@link TaxonBase taxon base}. <BR>
1139 * If taxonBase is of type taxon the same object is returned. If taxonBase is of type
1140 * synonym the accepted taxon is returned if one exists. If no accepted taxon exists
1141 * <code>null</code> is returned. If multiple accepted taxa exist the one taxon with the
1142 * same secundum reference is returned. If no such single taxon exists an
1143 * {@link IllegalStateException illegal state exception} is thrown.
1147 protected Taxon
getAcceptedTaxon(TaxonBase
<?
> taxonBase
) {
1148 if (taxonBase
== null){
1150 }else if(taxonBase
.isInstanceOf(Taxon
.class)){
1151 return CdmBase
.deproxy(taxonBase
, Taxon
.class);
1152 }else if(taxonBase
.isInstanceOf(Synonym
.class)){
1153 Synonym synonym
= CdmBase
.deproxy(taxonBase
, Synonym
.class);
1154 Set
<Taxon
> acceptedTaxa
= synonym
.getAcceptedTaxa();
1155 if (acceptedTaxa
.size() == 0){
1157 }else if (acceptedTaxa
.size() == 1){
1158 return acceptedTaxa
.iterator().next();
1160 Reference
<?
> sec
= synonym
.getSec();
1162 Set
<Taxon
> taxaWithSameSec
= new HashSet
<Taxon
>();
1163 for (Taxon taxon
: acceptedTaxa
){
1164 if (sec
.equals(taxon
.getSec())){
1165 taxaWithSameSec
.add(taxon
);
1168 if (taxaWithSameSec
.size() == 1){
1169 return taxaWithSameSec
.iterator().next();
1172 throw new IllegalStateException("Can't define the one accepted taxon for a synonym out of multiple accept taxa");
1175 throw new IllegalStateException("Unknown TaxonBase subclass: " + taxonBase
.getClass().getName());
1184 * @param readDataFromUrl
1185 * @see #READ_MEDIA_DATA
1187 * @throws MalformedURLException
1189 protected Media
getImageMedia(String uriString
, boolean readMediaData
) throws MalformedURLException
{
1190 if( uriString
== null){
1193 ImageInfo imageInfo
= null;
1195 uriString
= uriString
.replace(" ", "%20"); //replace whitespace
1197 uri
= new URI(uriString
);
1201 imageInfo
= ImageInfo
.NewInstance(uri
, 0);
1203 } catch (Exception e
) {
1204 String message
= "An error occurred when trying to read image meta data for " + uri
.toString() + ": " + e
.getMessage();
1205 logger
.warn(message
);
1206 fireWarningEvent(message
, "unknown location", 2, 0);
1208 ImageFile imageFile
= ImageFile
.NewInstance(uri
, null, imageInfo
);
1209 MediaRepresentation representation
= MediaRepresentation
.NewInstance();
1210 if(imageInfo
!= null){
1211 representation
.setMimeType(imageInfo
.getMimeType());
1212 representation
.setSuffix(imageInfo
.getSuffix());
1214 representation
.addRepresentationPart(imageFile
);
1215 Media media
= Media
.NewInstance();
1216 media
.addRepresentation(representation
);
1218 } catch (URISyntaxException e1
) {
1219 String message
= "An URISyntaxException occurred when trying to create uri from multimedia objcet string: " + uriString
;
1220 logger
.warn(message
);
1221 fireWarningEvent(message
, "unknown location", 4, 0);
1229 * Retrieves an Integer value from a result set. If the value is NULL null is returned.
1230 * ResultSet.getInt() returns 0 therefore we need a special handling for this case.
1234 * @throws SQLException
1236 protected Integer
nullSafeInt(ResultSet rs
, String columnName
) throws SQLException
{
1237 Object intObject
= rs
.getObject(columnName
);
1238 if (intObject
== null){
1241 return Integer
.valueOf(intObject
.toString());
1245 protected Double
nullSafeDouble(ResultSet rs
, String columnName
) throws SQLException
{
1246 Object doubleObject
= rs
.getObject(columnName
);
1247 if (doubleObject
== null){
1250 return Double
.valueOf(doubleObject
.toString());
1254 protected Float
nullSafeFloat(ResultSet rs
, String columnName
) throws SQLException
{
1255 Object doubleObject
= rs
.getObject(columnName
);
1256 if (doubleObject
== null){
1259 return Float
.valueOf(doubleObject
.toString());
1265 * Returns <code>null</code> for all blank strings. Identity function otherwise.
1269 protected String
NB(String str
) {
1270 if (StringUtils
.isBlank(str
)){