38ad3b46afa9ed2278501bf700ab8ec21071c9ee
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / common / CdmImportBase.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9
10 package eu.etaxonomy.cdm.io.common;
11
12 import java.net.MalformedURLException;
13 import java.net.URI;
14 import java.net.URISyntaxException;
15 import java.sql.ResultSet;
16 import java.sql.SQLException;
17 import java.util.Arrays;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Set;
21 import java.util.UUID;
22
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.log4j.Logger;
25
26 import eu.etaxonomy.cdm.api.service.pager.Pager;
27 import eu.etaxonomy.cdm.common.media.ImageInfo;
28 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
29 import eu.etaxonomy.cdm.io.common.mapping.IInputTransformer;
30 import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
31 import eu.etaxonomy.cdm.io.markup.MarkupTransformer;
32 import eu.etaxonomy.cdm.model.common.AnnotationType;
33 import eu.etaxonomy.cdm.model.common.CdmBase;
34 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
35 import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
36 import eu.etaxonomy.cdm.model.common.ExtensionType;
37 import eu.etaxonomy.cdm.model.common.Figure;
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.Representation;
47 import eu.etaxonomy.cdm.model.common.TermVocabulary;
48 import eu.etaxonomy.cdm.model.description.DescriptionBase;
49 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
50 import eu.etaxonomy.cdm.model.description.Feature;
51 import eu.etaxonomy.cdm.model.description.MeasurementUnit;
52 import eu.etaxonomy.cdm.model.description.Modifier;
53 import eu.etaxonomy.cdm.model.description.PresenceTerm;
54 import eu.etaxonomy.cdm.model.description.SpecimenDescription;
55 import eu.etaxonomy.cdm.model.description.State;
56 import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
57 import eu.etaxonomy.cdm.model.description.TaxonDescription;
58 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
59 import eu.etaxonomy.cdm.model.description.TextData;
60 import eu.etaxonomy.cdm.model.location.NamedArea;
61 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
62 import eu.etaxonomy.cdm.model.location.NamedAreaType;
63 import eu.etaxonomy.cdm.model.location.ReferenceSystem;
64 import eu.etaxonomy.cdm.model.media.ImageFile;
65 import eu.etaxonomy.cdm.model.media.Media;
66 import eu.etaxonomy.cdm.model.media.MediaRepresentation;
67 import eu.etaxonomy.cdm.model.name.NonViralName;
68 import eu.etaxonomy.cdm.model.name.Rank;
69 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
70 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
71 import eu.etaxonomy.cdm.model.reference.Reference;
72 import eu.etaxonomy.cdm.model.taxon.Classification;
73 import eu.etaxonomy.cdm.model.taxon.Synonym;
74 import eu.etaxonomy.cdm.model.taxon.Taxon;
75 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
76 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
77
78 /**
79 * @author a.mueller
80 * @created 01.07.2008
81 * @version 1.0
82 */
83 public abstract class CdmImportBase<CONFIG extends IImportConfigurator, STATE extends ImportStateBase> extends CdmIoBase<STATE> implements ICdmImport<CONFIG, STATE>{
84 private static Logger logger = Logger.getLogger(CdmImportBase.class);
85
86 protected static final boolean CREATE = true;
87 protected static final boolean IMAGE_GALLERY = true;
88 protected static final boolean READ_MEDIA_DATA = true;
89
90 public static final UUID uuidUserDefinedNamedAreaLevelVocabulary = UUID.fromString("255144da-8d95-457e-a327-9752a8f85e5a");
91 public static final UUID uuidUserDefinedNamedAreaVocabulary = UUID.fromString("b2238399-a3af-4f6d-b7eb-ff5d0899bf1b");
92 public static final UUID uuidUserDefinedExtensionTypeVocabulary = UUID.fromString("e28c1394-1be8-4847-8b81-ab44eb6d5bc8");
93 public static final UUID uuidUserDefinedReferenceSystemVocabulary = UUID.fromString("467591a3-10b4-4bf1-9239-f06ece33e90a");
94 public static final UUID uuidUserDefinedFeatureVocabulary = UUID.fromString("fe5fccb3-a2f2-4b97-b199-6e2743cf1627");
95 public static final UUID uuidUserDefinedMeasurementUnitVocabulary = UUID.fromString("d5e72bb7-f312-4080-bb86-c695d04a6e66");
96 public static final UUID uuidUserDefinedStatisticalMeasureVocabulary = UUID.fromString("62a89836-c730-4b4f-a904-3d859dbfc400");
97 public static final UUID uuidUserDefinedStateVocabulary = UUID.fromString("f7cddb49-8392-4db1-8640-65b48a0e6d13");
98 public static final UUID uuidUserDefinedTaxonRelationshipTypeVocabulary = UUID.fromString("31a324dc-408d-4877-891f-098db21744c6");
99 public static final UUID uuidUserDefinedAnnotationTypeVocabulary = UUID.fromString("cd9ecdd2-9cae-4890-9032-ad83293ae883");
100 public static final UUID uuidUserDefinedMarkerTypeVocabulary = UUID.fromString("5f02a261-fd7d-4fce-bbe4-21472de8cd51");
101 public static final UUID uuidUserDefinedRankVocabulary = UUID.fromString("4dc57931-38e2-46c3-974d-413b087646ba");
102
103 public static final UUID uuidUserDefinedModifierVocabulary = UUID.fromString("2a8b3838-3a95-49ea-9ab2-3049614b5884");
104
105
106
107 private static final String UuidOnly = "UUIDOnly";
108 private static final String UuidLabel = "UUID or label";
109 private static final String UuidLabelAbbrev = "UUID, label or abbreviation";
110 private static final String UuidAbbrev = "UUID or abbreviation";
111
112 public enum TermMatchMode{
113 UUID_ONLY(0, UuidOnly)
114 ,UUID_LABEL(1, UuidLabel)
115 ,UUID_LABEL_ABBREVLABEL(2, UuidLabelAbbrev)
116 ,UUID_ABBREVLABEL(3, UuidAbbrev)
117 ;
118
119
120 private int id;
121 private String representation;
122 private TermMatchMode(int id, String representation){
123 this.id = id;
124 this.representation = representation;
125 }
126 public int getId() {
127 return id;
128 }
129 public String getRepresentation() {
130 return representation;
131 }
132 public TermMatchMode valueOf(int id){
133 switch (id){
134 case 0: return UUID_ONLY;
135 case 1: return UUID_LABEL;
136 case 2: return UUID_LABEL_ABBREVLABEL;
137 case 3: return UUID_ABBREVLABEL;
138 default: return UUID_ONLY;
139 }
140 }
141
142
143 }
144
145 protected Classification makeTree(STATE state, Reference reference){
146 String treeName = "Classification (Import)";
147 if (reference != null && StringUtils.isNotBlank(reference.getTitleCache())){
148 treeName = reference.getTitleCache();
149 }
150 Classification tree = Classification.NewInstance(treeName);
151 tree.setReference(reference);
152
153
154 // use defined uuid for first tree
155 CONFIG config = (CONFIG)state.getConfig();
156 if (state.countTrees() < 1 ){
157 tree.setUuid(config.getClassificationUuid());
158 }
159 getClassificationService().save(tree);
160 state.putTree(reference, tree);
161 return tree;
162 }
163
164
165 /**
166 * Alternative memory saving method variant of
167 * {@link #makeTree(STATE state, Reference ref)} which stores only the
168 * UUID instead of the full tree in the <code>ImportStateBase</code> by
169 * using <code>state.putTreeUuid(ref, tree);</code>
170 *
171 * @param state
172 * @param ref
173 * @return
174 */
175 protected Classification makeTreeMemSave(STATE state, Reference ref){
176 String treeName = "Classification (Import)";
177 if (ref != null && StringUtils.isNotBlank(ref.getTitleCache())){
178 treeName = ref.getTitleCache();
179 }
180 Classification tree = Classification.NewInstance(treeName);
181 tree.setReference(ref);
182
183
184 // use defined uuid for first tree
185 CONFIG config = (CONFIG)state.getConfig();
186 if (state.countTrees() < 1 ){
187 tree.setUuid(config.getClassificationUuid());
188 }
189 getClassificationService().save(tree);
190 state.putTreeUuid(ref, tree);
191 return tree;
192 }
193
194
195 protected ExtensionType getExtensionType(STATE state, UUID uuid, String label, String text, String labelAbbrev){
196 return getExtensionType(state, uuid, label, text, labelAbbrev, null);
197 }
198 protected ExtensionType getExtensionType(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<ExtensionType> voc){
199 if (uuid == null){
200 uuid = UUID.randomUUID();
201 }
202 ExtensionType extensionType = state.getExtensionType(uuid);
203 if (extensionType == null){
204 extensionType = (ExtensionType)getTermService().find(uuid);
205 if (extensionType == null){
206 extensionType = ExtensionType.NewInstance(text, label, labelAbbrev);
207 extensionType.setUuid(uuid);
208 if (voc == null){
209 boolean isOrdered = false;
210 voc = getVocabulary(uuidUserDefinedExtensionTypeVocabulary, "User defined vocabulary for extension types", "User Defined Extension Types", null, null, isOrdered, extensionType);
211 }
212 voc.addTerm(extensionType);
213 getTermService().saveOrUpdate(extensionType);
214 }
215 state.putExtensionType(extensionType);
216 }
217 return extensionType;
218 }
219
220
221 protected MarkerType getMarkerType(STATE state, String keyString) {
222 IInputTransformer transformer = state.getTransformer();
223 MarkerType markerType = null;
224 try {
225 markerType = transformer.getMarkerTypeByKey(keyString);
226 } catch (UndefinedTransformerMethodException e) {
227 logger.info("getMarkerTypeByKey not yet implemented for this import");
228 }
229 if (markerType == null ){
230 UUID uuid;
231 try {
232 uuid = transformer.getMarkerTypeUuid(keyString);
233 return getMarkerType(state, uuid, keyString, keyString, keyString);
234 } catch (UndefinedTransformerMethodException e) {
235 logger.warn("getMarkerTypeUuid not yet implemented for this import");
236 }
237 }
238 return null;
239 }
240
241 protected MarkerType getMarkerType(STATE state, UUID uuid, String label, String text, String labelAbbrev){
242 return getMarkerType(state, uuid, label, text, labelAbbrev, null);
243 }
244
245
246 protected MarkerType getMarkerType(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<MarkerType> voc){
247 if (uuid == null){
248 uuid = UUID.randomUUID();
249 }
250 MarkerType markerType = state.getMarkerType(uuid);
251 if (markerType == null){
252 markerType = (MarkerType)getTermService().find(uuid);
253 if (markerType == null){
254 markerType = MarkerType.NewInstance(label, text, labelAbbrev);
255 markerType.setUuid(uuid);
256 if (voc == null){
257 boolean isOrdered = false;
258 voc = getVocabulary(uuidUserDefinedMarkerTypeVocabulary, "User defined vocabulary for marker types", "User Defined Marker Types", null, null, isOrdered, markerType);
259 }
260 voc.addTerm(markerType);
261 getTermService().save(markerType);
262 }
263 state.putMarkerType(markerType);
264 }
265 return markerType;
266 }
267
268 protected AnnotationType getAnnotationType(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<AnnotationType> voc){
269 if (uuid == null){
270 uuid = UUID.randomUUID();
271 }
272 AnnotationType annotationType = state.getAnnotationType(uuid);
273 if (annotationType == null){
274 annotationType = (AnnotationType)getTermService().find(uuid);
275 if (annotationType == null){
276 annotationType = AnnotationType.NewInstance(label, text, labelAbbrev);
277 annotationType.setUuid(uuid);
278 if (voc == null){
279 boolean isOrdered = false;
280 voc = getVocabulary(uuidUserDefinedAnnotationTypeVocabulary, "User defined vocabulary for annotation types", "User Defined Annotation Types", null, null, isOrdered, annotationType);
281 }
282
283 voc.addTerm(annotationType);
284 getTermService().save(annotationType);
285 }
286 state.putAnnotationType(annotationType);
287 }
288 return annotationType;
289 }
290
291
292 protected ReferenceSystem getReferenceSystem(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary voc){
293 if (uuid == null){
294 uuid = UUID.randomUUID();
295 }
296 ReferenceSystem refSystem = state.getReferenceSystem(uuid);
297 if (refSystem == null){
298 refSystem = (ReferenceSystem)getTermService().find(uuid);
299 if (refSystem == null){
300 refSystem = ReferenceSystem.NewInstance(text, label, labelAbbrev);
301 if (voc == null){
302 boolean isOrdered = false;
303 voc = getVocabulary(uuidUserDefinedReferenceSystemVocabulary, "User defined vocabulary for reference systems", "User Defined Reference System", null, null, isOrdered, refSystem);
304 }
305 voc.addTerm(refSystem);
306 refSystem.setUuid(uuid);
307 getTermService().save(refSystem);
308 }
309 state.putReferenceSystem(refSystem);
310 }
311 return refSystem;
312
313 }
314
315
316
317 protected Rank getRank(STATE state, UUID uuid, String label, String text, String labelAbbrev,OrderedTermVocabulary<Rank> voc, Rank lowerRank){
318 if (uuid == null){
319 uuid = UUID.randomUUID();
320 }
321 Rank rank = state.getRank(uuid);
322 if (rank == null){
323 rank = (Rank)getTermService().find(uuid);
324 if (rank == null){
325 rank = new Rank(text, label, labelAbbrev);
326 if (voc == null){
327 boolean isOrdered = true;
328 voc = (OrderedTermVocabulary)getVocabulary(uuidUserDefinedRankVocabulary, "User defined vocabulary for ranks", "User Defined Reference System", null, null, isOrdered, rank);
329 }
330 if (lowerRank == null){
331 voc.addTerm(rank);
332 }else{
333 voc.addTermAbove(rank, lowerRank);
334 }
335 rank.setUuid(uuid);
336 getTermService().save(rank);
337 }
338 state.putRank(rank);
339 }
340 return rank;
341
342 }
343
344 /**
345 * Returns a named area for a given uuid by first . If the named area does not
346 * @param state
347 * @param uuid
348 * @param label
349 * @param text
350 * @param labelAbbrev
351 * @param areaType
352 * @param level
353 * @return
354 */
355 protected NamedArea getNamedArea(STATE state, UUID uuid, String label, String text, String labelAbbrev, NamedAreaType areaType, NamedAreaLevel level){
356 return getNamedArea(state, uuid, label, text, labelAbbrev, areaType, level, null, null);
357 }
358
359 protected NamedArea getNamedArea(STATE state, UUID uuid, String label, String text, String labelAbbrev, NamedAreaType areaType, NamedAreaLevel level, TermVocabulary voc, TermMatchMode matchMode){
360 Class<NamedArea> clazz = NamedArea.class;
361 if (uuid == null){
362 uuid = UUID.randomUUID();
363 }
364 if (matchMode == null){
365 matchMode = TermMatchMode.UUID_ONLY;
366 }
367 NamedArea namedArea = state.getNamedArea(uuid);
368 if (namedArea == null){
369 DefinedTermBase<?> term = getTermService().find(uuid);
370 namedArea = CdmBase.deproxy(term,NamedArea.class);
371 //TODO matching still experimental
372 if (namedArea == null && (matchMode.equals(TermMatchMode.UUID_LABEL) || matchMode.equals(TermMatchMode.UUID_LABEL_ABBREVLABEL ))){
373 //TODO test
374 Pager<NamedArea> areaPager = (Pager)getTermService().findByTitle(clazz, label, null, null, null, null, null, null);
375 namedArea = findBestMatchingArea(areaPager, uuid, label, text, labelAbbrev, areaType, level, voc);
376 }
377 if (namedArea == null && (matchMode.equals(TermMatchMode.UUID_ABBREVLABEL) || matchMode.equals(TermMatchMode.UUID_LABEL_ABBREVLABEL))){
378 Pager<NamedArea> areaPager = getTermService().findByRepresentationAbbreviation(labelAbbrev, clazz, null, null);
379 namedArea = findBestMatchingArea(areaPager, uuid, label, text, labelAbbrev, areaType, level, voc);
380 }
381
382 if (namedArea == null){
383 namedArea = NamedArea.NewInstance(text, label, labelAbbrev);
384 if (voc == null){
385 boolean isOrdered = true;
386 voc = getVocabulary(uuidUserDefinedNamedAreaVocabulary, "User defined vocabulary for named areas", "User Defined Named Areas", null, null, isOrdered, namedArea);
387 }
388 voc.addTerm(namedArea);
389 namedArea.setType(areaType);
390 namedArea.setLevel(level);
391 namedArea.setUuid(uuid);
392 getTermService().save(namedArea);
393 }
394 state.putNamedArea(namedArea);
395 }
396 return namedArea;
397 }
398
399
400 private NamedArea findBestMatchingArea(Pager<NamedArea> areaPager, UUID uuid, String label, String text, String abbrev,
401 NamedAreaType areaType, NamedAreaLevel level, TermVocabulary voc) {
402 // TODO preliminary implementation
403 List<NamedArea> list = areaPager.getRecords();
404 if (list.size() == 0){
405 return null;
406 }else if (list.size() == 1){
407 return list.get(0);
408 }else if (list.size() > 1){
409 String message = "There is more than 1 matching area for %s, %s, %s. As a preliminary implementation I take the first";
410 message = String.format(message, label, abbrev, text);
411 logger.warn(message);
412 return list.get(0);
413 }
414 return null;
415 }
416
417
418 protected NamedAreaLevel getNamedAreaLevel(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<NamedAreaLevel> voc){
419 if (uuid == null){
420 uuid = UUID.randomUUID();
421 }
422 NamedAreaLevel namedAreaLevel = state.getNamedAreaLevel(uuid);
423 if (namedAreaLevel == null){
424 //TODO propPath just for testing
425 List<String> propPath = Arrays.asList("vocabulary");
426 DefinedTermBase<NamedAreaLevel> term = getTermService().load(uuid, propPath);
427 namedAreaLevel = CdmBase.deproxy(term, NamedAreaLevel.class);
428 if (namedAreaLevel == null){
429 namedAreaLevel = NamedAreaLevel.NewInstance(text, label, labelAbbrev);
430 if (voc == null){
431 boolean isOrdered = true;
432 voc = getVocabulary(uuidUserDefinedNamedAreaLevelVocabulary, "User defined vocabulary for named area levels", "User Defined Named Area Levels", null, null, isOrdered, namedAreaLevel);
433 }
434 //FIXME only for debugging
435 Set<NamedAreaLevel> terms = voc.getTerms();
436 for (NamedAreaLevel level : terms){
437 TermVocabulary<NamedAreaLevel> levelVoc = level.getVocabulary();
438 if (levelVoc == null){
439 logger.error("ONLY FOR DEBUG: Level voc is null");
440 }else{
441 logger.info("ONLY FOR DEBUG: Level voc is not null");
442 }
443 }
444 voc.addTerm(namedAreaLevel);
445 namedAreaLevel.setUuid(uuid);
446 getTermService().save(namedAreaLevel);
447 }
448 state.putNamedAreaLevel(namedAreaLevel);
449 }
450 return namedAreaLevel;
451 }
452
453 /**
454 * Returns a {@link State} if it exists. <code>null</code> otherwise.
455 * @param state
456 * @param uuid
457 * @return {@link State}
458 */
459 protected State getStateTerm(STATE state, UUID uuid){
460 return getStateTerm(state, uuid, null, null, null, null);
461 }
462
463
464 /**
465 * Returns a {@link State} for a given uuid by first checking if the uuid has already been used in this import, if not
466 * checking if the state exists in the database, if not creating it anew (with vocabulary etc.).
467 * If label, text and labelAbbrev are all <code>null</code> no state is created.
468 * @param importState
469 * @param uuid
470 * @param label
471 * @param text
472 * @param labelAbbrev
473 * @param voc
474 * @return
475 */
476 protected State getStateTerm(STATE importState, UUID uuid, String label, String text, String labelAbbrev, OrderedTermVocabulary<State> voc) {
477 if (uuid == null){
478 return null;
479 }
480 State stateTerm = importState.getStateTerm(uuid);
481 if (stateTerm == null){
482 stateTerm = CdmBase.deproxy(getTermService().find(uuid), State.class);
483 if (stateTerm == null && ! hasNoLabel(label, text, labelAbbrev)){
484 stateTerm = State.NewInstance(text, label, labelAbbrev);
485 stateTerm.setUuid(uuid);
486 if (voc == null){
487 boolean isOrdered = true;
488 TermVocabulary<State> orderedVoc = getVocabulary(uuidUserDefinedStateVocabulary, "User defined vocabulary for states used by Categorical Data", "User Defined States", null, null, isOrdered, stateTerm);
489 voc = CdmBase.deproxy(orderedVoc, OrderedTermVocabulary.class);
490 }
491 voc.addTerm(stateTerm);
492 getTermService().save(stateTerm);
493 }else{
494 logger.warn("No label provided for new state with uuid " + uuid);
495 }
496 importState.putStateTerm(stateTerm);
497 }
498 return stateTerm;
499 }
500
501 /**
502 * Returns a feature if it exists, null otherwise.
503 * @see #getFeature(ImportStateBase, UUID, String, String, String, TermVocabulary)
504 * @param state
505 * @param uuid
506 * @return
507 */
508 protected Feature getFeature(STATE state, UUID uuid){
509 return getFeature(state, uuid, null, null, null, null);
510 }
511
512 /**
513 * Returns a feature for a given uuid by first checking if the uuid has already been used in this import, if not
514 * checking if the feature exists in the database, if not creating it anew (with vocabulary etc.).
515 * If label, text and labelAbbrev are all <code>null</code> no feature is created.
516 * @param state
517 * @param uuid
518 * @param label
519 * @param text
520 * @param labelAbbrev
521 * @return
522 */
523 protected Feature getFeature(STATE state, UUID uuid, String label, String description, String labelAbbrev, TermVocabulary<Feature> voc){
524 if (uuid == null){
525 return null;
526 }
527 Feature feature = state.getFeature(uuid);
528 if (feature == null){
529 feature = (Feature)getTermService().find(uuid);
530 if (feature == null && ! hasNoLabel(label, description, labelAbbrev)){
531 feature = Feature.NewInstance(description, label, labelAbbrev);
532 feature.setUuid(uuid);
533 feature.setSupportsTextData(true);
534 // UUID uuidFeatureVoc = UUID.fromString("b187d555-f06f-4d65-9e53-da7c93f8eaa8");
535 if (voc == null){
536 boolean isOrdered = false;
537 voc = getVocabulary(uuidUserDefinedFeatureVocabulary, "User defined vocabulary for features", "User Defined Features", null, null, isOrdered, feature);
538 }
539 voc.addTerm(feature);
540 getTermService().save(feature);
541 }
542 state.putFeature(feature);
543 }
544 return feature;
545 }
546
547 /**
548 * Returns a {@link MeasurementUnit} for a given uuid by first checking if the uuid has already been used in this import, if not
549 * checking if the {@link MeasurementUnit} exists in the database, if not creating it anew (with vocabulary etc.).
550 * If label, text and labelAbbrev are all <code>null</code> no {@link MeasurementUnit} is created.
551 * @param state
552 * @param uuid
553 * @param label
554 * @param text
555 * @param labelAbbrev
556 * @return
557 */
558 protected MeasurementUnit getMeasurementUnit(STATE state, UUID uuid, String label, String description, String labelAbbrev, TermVocabulary<MeasurementUnit> voc){
559 if (uuid == null){
560 return null;
561 }
562 MeasurementUnit unit = state.getMeasurementUnit(uuid);
563 if (unit == null){
564 unit = (MeasurementUnit)getTermService().find(uuid);
565 if (unit == null && ! hasNoLabel(label, description, labelAbbrev)){
566 unit = MeasurementUnit.NewInstance(description, label, labelAbbrev);
567 unit.setUuid(uuid);
568 if (voc == null){
569 boolean isOrdered = false;
570 voc = getVocabulary(uuidUserDefinedMeasurementUnitVocabulary, "User defined vocabulary for measurement units", "User Defined Measurement Units", null, null, isOrdered, unit);
571 }
572 voc.addTerm(unit);
573 getTermService().save(unit);
574 }
575 state.putMeasurementUnit(unit);
576 }
577 return unit;
578 }
579
580 /**
581 * Returns a {@link StatisticalMeasure} for a given uuid by first checking if the uuid has already been used in this import, if not
582 * checking if the {@link StatisticalMeasure} exists in the database, if not creating it anew (with vocabulary etc.).
583 * If label, text and labelAbbrev are all <code>null</code> no {@link StatisticalMeasure} is created.
584 * @param state
585 * @param uuid
586 * @param label
587 * @param text
588 * @param labelAbbrev
589 * @return
590 */
591 protected StatisticalMeasure getStatisticalMeasure(STATE state, UUID uuid, String label, String description, String labelAbbrev, TermVocabulary<StatisticalMeasure> voc){
592 if (uuid == null){
593 return null;
594 }
595 StatisticalMeasure statisticalMeasure = state.getStatisticalMeasure(uuid);
596 if (statisticalMeasure == null){
597 statisticalMeasure = (StatisticalMeasure)getTermService().find(uuid);
598 if (statisticalMeasure == null && ! hasNoLabel(label, description, labelAbbrev)){
599 statisticalMeasure = StatisticalMeasure.NewInstance(description, label, labelAbbrev);
600 statisticalMeasure.setUuid(uuid);
601 if (voc == null){
602 boolean isOrdered = false;
603 voc = getVocabulary(uuidUserDefinedStatisticalMeasureVocabulary, "User defined vocabulary for statistical measures", "User Defined Statistical Measures", null, null, isOrdered, statisticalMeasure);
604 }
605 voc.addTerm(statisticalMeasure);
606 getTermService().save(statisticalMeasure);
607 }
608 state.putStatisticalMeasure(statisticalMeasure);
609 }
610 return statisticalMeasure;
611 }
612
613 /**
614 * Returns a {@link Modifier} for a given uuid by first checking if the uuid has already been used in this import, if not
615 * checking if the {@link Modifier} exists in the database, if not creating it anew (with vocabulary etc.).
616 * If label, text and labelAbbrev are all <code>null</code> no {@link Modifier} is created.
617 * @param state
618 * @param uuid
619 * @param label
620 * @param text
621 * @param labelAbbrev
622 * @return
623 */
624 protected Modifier getModifier(STATE state, UUID uuid, String label, String description, String labelAbbrev, TermVocabulary<Modifier> voc){
625 if (uuid == null){
626 return null;
627 }
628 Modifier modifier = state.getModifier(uuid);
629 if (modifier == null){
630 modifier = (Modifier)getTermService().find(uuid);
631 if (modifier == null && ! hasNoLabel(label, description, labelAbbrev)){
632 modifier = Modifier.NewInstance(description, label, labelAbbrev);
633 modifier.setUuid(uuid);
634 if (voc == null){
635 boolean isOrdered = false;
636 voc = getVocabulary(uuidUserDefinedModifierVocabulary, "User defined vocabulary for modifier", "User Defined Modifier", null, null, isOrdered, modifier);
637 }
638 voc.addTerm(modifier);
639 getTermService().save(modifier);
640 }
641 state.putModifier(modifier);
642 }
643 return modifier;
644 }
645
646 /**
647 * Returns a taxon relationship type for a given uuid by first checking if the uuid has already been used in this import, if not
648 * checking if the taxon relationship type exists in the database, if not creating it anew (with vocabulary etc.).
649 * If label, text and labelAbbrev are all <code>null</code> no taxon relationship type is created.
650 * @param state
651 * @param uuid
652 * @param label
653 * @param text
654 * @param labelAbbrev
655 * @return
656 */
657 protected TaxonRelationshipType getTaxonRelationshipType(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<TaxonRelationshipType> voc){
658 if (uuid == null){
659 return null;
660 }
661 TaxonRelationshipType relType = state.getTaxonRelationshipType(uuid);
662 if (relType == null){
663 relType = (TaxonRelationshipType)getTermService().find(uuid);
664 if (relType == null && ! hasNoLabel(label, text, labelAbbrev)){
665 relType = new TaxonRelationshipType();
666 Representation repr = Representation.NewInstance(text, label, labelAbbrev, Language.DEFAULT());
667 relType.addRepresentation(repr);
668 relType.setUuid(uuid);
669 if (voc == null){
670 boolean isOrdered = true;
671 voc = getVocabulary(uuidUserDefinedTaxonRelationshipTypeVocabulary, "User defined vocabulary for taxon relationship types", "User Defined Taxon Relationship Types", null, null, isOrdered, relType);
672 }
673 voc.addTerm(relType);
674 getTermService().save(relType);
675 }
676 state.putTaxonRelationshipType(relType);
677 }
678 return relType;
679 }
680
681 private boolean hasNoLabel(String label, String text, String labelAbbrev) {
682 return label == null && text == null && labelAbbrev == null;
683 }
684
685
686 /**
687 * Returns a presence term for a given uuid by first ...
688 * @param state
689 * @param uuid
690 * @param label
691 * @param text
692 * @param labelAbbrev
693 * @return
694 */
695 protected PresenceTerm getPresenceTerm(STATE state, UUID uuid, String label, String text, String labelAbbrev){
696 if (uuid == null){
697 return null;
698 }
699 PresenceTerm presenceTerm = state.getPresenceTerm(uuid);
700 if (presenceTerm == null){
701 presenceTerm = (PresenceTerm)getTermService().find(uuid);
702 if (presenceTerm == null){
703 presenceTerm = PresenceTerm.NewInstance(text, label, labelAbbrev);
704 presenceTerm.setUuid(uuid);
705 //set vocabulary ; FIXME use another user-defined vocabulary
706 UUID uuidPresenceVoc = UUID.fromString("adbbbe15-c4d3-47b7-80a8-c7d104e53a05");
707 TermVocabulary<PresenceTerm> voc = getVocabularyService().find(uuidPresenceVoc);
708 voc.addTerm(presenceTerm);
709 getTermService().save(presenceTerm);
710 }
711 state.putPresenceTerm(presenceTerm);
712 }
713 return presenceTerm;
714 }
715
716 /**
717 * Returns a language for a given uuid by first ...
718 * @param state
719 * @param uuid
720 * @param label
721 * @param text
722 * @param labelAbbrev
723 * @return
724 */
725 protected Language getLanguage(STATE state, UUID uuid, String label, String text, String labelAbbrev){
726 return getLanguage(state, uuid, label, text, labelAbbrev, null);
727 }
728
729 protected Language getLanguage(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary voc){
730 if (uuid == null){
731 return null;
732 }
733 Language language = state.getLanguage(uuid);
734 if (language == null){
735 language = (Language)getTermService().find(uuid);
736 if (language == null){
737 language = Language.NewInstance(text, label, labelAbbrev);
738
739 language.setUuid(uuid);
740 if (voc == null){
741 UUID uuidLanguageVoc = UUID.fromString("463a96f1-20ba-4a4c-9133-854c1682bd9b");
742 boolean isOrdered = false;
743 voc = getVocabulary(uuidLanguageVoc, "User defined languages", "User defined languages", "User defined languages", null, isOrdered, language);
744 }
745 //set vocabulary ; FIXME use another user-defined vocabulary
746
747 voc.addTerm(language);
748 getTermService().save(language);
749 }
750 state.putLanguage(language);
751 }
752 return language;
753 }
754
755
756 /**
757 * @param uuid
758 * @return
759 *
760 */
761 protected <T extends DefinedTermBase> TermVocabulary<T> getVocabulary(UUID uuid, String text, String label, String abbrev, URI termSourceUri, boolean isOrdered, T type) {
762 List<String> propPath = Arrays.asList(new String[]{"terms"});
763 TermVocabulary<T> voc = getVocabularyService().load(uuid, propPath);
764 if (voc == null){
765 if (isOrdered){
766 voc = OrderedTermVocabulary.NewInstance(text, label, abbrev, termSourceUri);
767 }else{
768 voc = TermVocabulary.NewInstance(text, label, abbrev, termSourceUri);
769 }
770 voc.setUuid(uuid);
771 getVocabularyService().save(voc);
772 }
773 return voc;
774 }
775
776 /**
777 * Adds an orginal source to a sourceable objects (implemented for Identifiable entity and description element.
778 * If cdmBase is not sourceable nothing happens.
779 * TODO Move to DbImportBase once this exists.
780 * TODO also implemented in DbImportObjectCreationMapper (reduce redundance)
781 * @param rs
782 * @param cdmBase
783 * @param dbIdAttribute
784 * @param namespace
785 * @param citation
786 * @throws SQLException
787 */
788 public void addOriginalSource(CdmBase cdmBase, Object idAttributeValue, String namespace, Reference citation) {
789 if (cdmBase instanceof ISourceable ){
790 IOriginalSource source;
791 ISourceable sourceable = (ISourceable)cdmBase;
792 Object id = idAttributeValue;
793 String strId = String.valueOf(id);
794 String microCitation = null;
795 if (cdmBase instanceof IdentifiableEntity){
796 source = IdentifiableSource.NewInstance(strId, namespace, citation, microCitation);
797 }else if (cdmBase instanceof DescriptionElementBase){
798 source = DescriptionElementSource.NewInstance(strId, namespace, citation, microCitation);
799 }else{
800 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.");
801 return;
802 }
803 sourceable.addSource(source);
804 }else if (cdmBase != null){
805 logger.warn("Sourced object does not implement ISourceable: " + cdmBase.getClass() + "," + cdmBase.getUuid());
806 }else{
807 logger.warn("Sourced object is null");
808 }
809 }
810
811 /**
812 * @see #addOriginalSource(CdmBase, Object, String, Reference)
813 * @param rs
814 * @param cdmBase
815 * @param dbIdAttribute
816 * @param namespace
817 * @param citation
818 * @throws SQLException
819 */
820 public void addOriginalSource(ResultSet rs, CdmBase cdmBase, String dbIdAttribute, String namespace, Reference citation) throws SQLException {
821 Object id = rs.getObject(dbIdAttribute);
822 addOriginalSource(cdmBase, id, namespace, citation);
823 }
824
825
826 /**
827 * If the child taxon is missing genus or species epithet information and the rank is below <i>genus</i>
828 * or <i>species</i> respectively the according epithets are taken from the parent taxon.
829 * If the name is an autonym and has no combination author/basionym author the authors are taken from
830 * the parent.
831 * @param parentTaxon
832 * @param childTaxon
833 */
834 protected void fillMissingEpithetsForTaxa(Taxon parentTaxon, Taxon childTaxon) {
835 NonViralName parentName = HibernateProxyHelper.deproxy(parentTaxon.getName(), NonViralName.class);
836 NonViralName childName = HibernateProxyHelper.deproxy(childTaxon.getName(), NonViralName.class);
837 fillMissingEpithets(parentName, childName);
838 }
839
840 /**
841 * If the child name is missing genus or species epithet information and the rank is below <i>genus</i>
842 * or <i>species</i> respectively the according epithets are taken from the parent name.
843 * If the name is an autonym and has no combination author/basionym author the authors are taken from
844 * the parent.
845 * @param parentTaxon
846 * @param childTaxon
847 */
848 protected void fillMissingEpithets(NonViralName parentName, NonViralName childName) {
849 if (StringUtils.isBlank(childName.getGenusOrUninomial()) && childName.getRank().isLower(Rank.GENUS()) ){
850 childName.setGenusOrUninomial(parentName.getGenusOrUninomial());
851 }
852
853 if (StringUtils.isBlank(childName.getSpecificEpithet()) && childName.getRank().isLower(Rank.SPECIES()) ){
854 childName.setSpecificEpithet(parentName.getSpecificEpithet());
855 }
856 if (childName.isAutonym() && childName.getCombinationAuthorTeam() == null && childName.getBasionymAuthorTeam() == null ){
857 childName.setCombinationAuthorTeam(parentName.getCombinationAuthorTeam());
858 childName.setBasionymAuthorTeam(parentName.getBasionymAuthorTeam());
859 }
860 }
861
862 /**
863 * Returns the taxon description for a taxon. If there are multiple taxon descriptions
864 * an arbitrary one is chosen.
865 * If no taxon description exists, a new one is created if <code>createNewIfNotExists</code>
866 * is <code>true</code>.
867 * @param createNewIfNotExists
868 * @param isImageGallery if true only taxon description being image galleries are considered.
869 * If false only taxon description being no image galleries are considered.
870 * @return
871 */
872 public TaxonNameDescription getTaxonNameDescription(TaxonNameBase name, boolean isImageGallery, boolean createNewIfNotExists) {
873 Reference ref = null;
874 return getTaxonNameDescription(name, ref, isImageGallery, createNewIfNotExists);
875 }
876
877 /**
878 * Like {@link #getTaxonDescription(Taxon, boolean, boolean)}
879 * Only matches a description if the given reference is a source of the description.<BR>
880 * If a new description is created the given reference will be added as a source.
881 *
882 * @see #getTaxonDescription(Taxon, boolean, boolean)
883 */
884 public TaxonNameDescription getTaxonNameDescription(TaxonNameBase<?,?> name, Reference ref, boolean isImageGallery, boolean createNewIfNotExists) {
885 TaxonNameDescription result = null;
886 Set<TaxonNameDescription> descriptions= name.getDescriptions();
887 for (TaxonNameDescription description : descriptions){
888 if (description.isImageGallery() == isImageGallery){
889 if (hasCorrespondingSource(ref, description)){
890 result = description;
891 break;
892 }
893 }
894 }
895 if (result == null && createNewIfNotExists){
896 result = TaxonNameDescription.NewInstance(name);
897 result.setImageGallery(isImageGallery);
898 if (ref != null){
899 result.addSource(null, null, ref, null);
900 }
901 }
902 return result;
903 }
904
905 /**
906 * Returns the taxon description for a taxon. If there are multiple taxon descriptions
907 * an arbitrary one is chosen.
908 * If no taxon description exists, a new one is created if <code>createNewIfNotExists</code>
909 * is <code>true</code>.
910 * @param createNewIfNotExists
911 * @param isImageGallery if true only taxon description being image galleries are considered.
912 * If false only taxon description being no image galleries are considered.
913 * @return
914 */
915 public TaxonDescription getTaxonDescription(Taxon taxon, boolean isImageGallery, boolean createNewIfNotExists) {
916 Reference<?> ref = null;
917 return getTaxonDescription(taxon, ref, isImageGallery, createNewIfNotExists);
918 }
919
920 /**
921 * Like {@link #getTaxonDescription(Taxon, boolean, boolean)}
922 * Only matches a description if the given reference is a source of the description.<BR>
923 * If a new description is created the given reference will be added as a source.
924 *
925 * @see #getTaxonDescription(Taxon, boolean, boolean)
926 */
927 public TaxonDescription getTaxonDescription(Taxon taxon, Reference ref, boolean isImageGallery, boolean createNewIfNotExists) {
928 TaxonDescription result = null;
929 Set<TaxonDescription> descriptions= taxon.getDescriptions();
930 for (TaxonDescription description : descriptions){
931 if (description.isImageGallery() == isImageGallery){
932 if (hasCorrespondingSource(ref, description)){
933 result = description;
934 break;
935 }
936 }
937 }
938 if (result == null && createNewIfNotExists){
939 result = TaxonDescription.NewInstance(taxon);
940 result.setImageGallery(isImageGallery);
941 if (ref != null){
942 result.addSource(null, null, ref, null);
943 }
944 }
945 return result;
946 }
947
948
949 /**
950 * Returns the {@link SpecimenDescription specimen description} for a {@link SpecimenOrObservationBase specimen or observation}.
951 * If there are multiple specimen descriptions an arbitrary one is chosen.
952 * If no specimen description exists, a new one is created if <code>createNewIfNotExists</code> is <code>true</code>.
953 * @param createNewIfNotExists
954 * @param isImageGallery if true only specimen description being image galleries are considered.
955 * If false only specimen description being no image galleries are considered.
956 * @return
957 */
958 public SpecimenDescription getSpecimenDescription(SpecimenOrObservationBase specimen, boolean isImageGallery, boolean createNewIfNotExists) {
959 Reference ref = null;
960 return getSpecimenDescription(specimen, ref, isImageGallery, createNewIfNotExists);
961 }
962
963 /**
964 * Like {@link #getSpecimenDescription(SpecimenOrObservationBase, boolean, boolean)}
965 * Only matches a description if the given reference is a source of the description.<BR>
966 * If a new description is created the given reference will be added as a source.
967 *
968 * @see #getTaxonDescription(Taxon, boolean, boolean)
969 */
970 public SpecimenDescription getSpecimenDescription(SpecimenOrObservationBase specimen, Reference ref, boolean isImageGallery, boolean createNewIfNotExists) {
971 SpecimenDescription result = null;
972 Set<SpecimenDescription> descriptions= specimen.getDescriptions();
973 for (SpecimenDescription description : descriptions){
974 if (description.isImageGallery() == isImageGallery){
975 if (hasCorrespondingSource(ref, description)){
976 result = description;
977 break;
978 }
979 }
980 }
981 if (result == null && createNewIfNotExists){
982 result = SpecimenDescription.NewInstance(specimen);
983 result.setImageGallery(isImageGallery);
984 if (ref != null){
985 result.addSource(null, null, ref, null);
986 }
987 }
988 return result;
989 }
990
991
992 /**
993 * Returns the textdata that holds general information about a feature for a taxon description.
994 * This is mainly necessary for descriptions that have more than one description element for
995 * a given feature such as 'distribution', 'description' or 'common name'. It may also hold
996 * for hierarchical features where no description element exists for a higher hierarchy level.
997 * Example: the description feature has subfeatures. But some information like authorship, figures,
998 * sources need to be added to the description itself.
999 * Currently a feature placeholder is marked by a marker of type 'feature placeholder'. Maybe in future
1000 * there will be a boolean marker in the TextData class itself.
1001 * @param state
1002 * @param feature
1003 * @param taxon
1004 * @param ref
1005 * @param createIfNotExists
1006 * @return
1007 */
1008 protected TextData getFeaturePlaceholder(STATE state, DescriptionBase<?> description, Feature feature, boolean createIfNotExists) {
1009 UUID featurePlaceholderUuid = MarkupTransformer.uuidFeaturePlaceholder;
1010 for (DescriptionElementBase element : description.getElements()){
1011 if (element.isInstanceOf(TextData.class)){
1012 TextData textData = CdmBase.deproxy(element, TextData.class);
1013 if (textData.getFeature() == null || ! textData.getFeature().equals(feature)){
1014 continue;
1015 }
1016 for (Marker marker : textData.getMarkers()){
1017 MarkerType markerType = marker.getMarkerType();
1018 if (markerType != null &&
1019 markerType.getUuid().equals(featurePlaceholderUuid) &&
1020 marker.getValue() == true){
1021 return textData;
1022 }
1023 }
1024 }
1025 }
1026 if (createIfNotExists){
1027 TextData newPlaceholder = TextData.NewInstance(feature);
1028 MarkerType placeholderMarkerType = getMarkerType(state, featurePlaceholderUuid, "Feature Placeholder", "Feature Placeholder", null);
1029 Marker marker = Marker.NewInstance(placeholderMarkerType, true);
1030 newPlaceholder.addMarker(marker);
1031 description.addElement(newPlaceholder);
1032 return newPlaceholder;
1033 }else{
1034 return null;
1035 }
1036 }
1037
1038
1039
1040 /**
1041 * Returns true, if this description has a source with a citation equal to the given reference.
1042 * Returns true if the given reference is null.
1043 * @param ref
1044 * @param description
1045 */
1046 private boolean hasCorrespondingSource(Reference<?> ref, DescriptionBase<?> description) {
1047 if (ref != null){
1048 for (IdentifiableSource source : description.getSources()){
1049 if (ref.equals(source.getCitation())){
1050 return true;
1051 }
1052 }
1053 return false;
1054 }
1055 return true;
1056
1057 }
1058
1059
1060 /**
1061 * Returns the accepted taxon of a {@link TaxonBase taxon base}. <BR>
1062 * If taxonBase is of type taxon the same object is returned. If taxonBase is of type
1063 * synonym the accepted taxon is returned if one exists. If no accepted taxon exists
1064 * <code>null</code> is returned. If multiple accepted taxa exist the one taxon with the
1065 * same secundum reference is returned. If no such single taxon exists an
1066 * {@link IllegalStateException illegal state exception} is thrown.
1067 * @param taxonBase
1068 * @return
1069 */
1070 protected Taxon getAcceptedTaxon(TaxonBase<?> taxonBase) {
1071 if (taxonBase == null){
1072 return null;
1073 }else if(taxonBase.isInstanceOf(Taxon.class)){
1074 return CdmBase.deproxy(taxonBase, Taxon.class);
1075 }else if(taxonBase.isInstanceOf(Synonym.class)){
1076 Synonym synonym = CdmBase.deproxy(taxonBase, Synonym.class);
1077 Set<Taxon> acceptedTaxa = synonym.getAcceptedTaxa();
1078 if (acceptedTaxa.size() == 0){
1079 return null;
1080 }else if (acceptedTaxa.size() == 1){
1081 return acceptedTaxa.iterator().next();
1082 }else{
1083 Reference<?> sec = synonym.getSec();
1084 if (sec != null){
1085 Set<Taxon> taxaWithSameSec = new HashSet<Taxon>();
1086 for (Taxon taxon: acceptedTaxa){
1087 if (sec.equals(taxon.getSec())){
1088 taxaWithSameSec.add(taxon);
1089 }
1090 }
1091 if (taxaWithSameSec.size() == 1){
1092 return taxaWithSameSec.iterator().next();
1093 }
1094 }
1095 throw new IllegalStateException("Can't define the one accepted taxon for a synonym out of multiple accept taxa");
1096 }
1097 }else{
1098 throw new IllegalStateException("Unknown TaxonBase subclass: " + taxonBase.getClass().getName());
1099 }
1100 }
1101
1102
1103
1104 /**
1105 * Creates
1106 * @param uriString
1107 * @param readDataFromUrl
1108 * @see #READ_MEDIA_DATA
1109 * @return
1110 * @throws MalformedURLException
1111 */
1112 protected Media getImageMedia(String uriString, boolean readMediaData, boolean isFigure) throws MalformedURLException {
1113 if( uriString == null){
1114 return null;
1115 } else {
1116 ImageInfo imageInfo = null;
1117 URI uri;
1118 uriString = uriString.replace(" ", "%20"); //replace whitespace
1119 try {
1120 uri = new URI(uriString);
1121 try {
1122 if (readMediaData){
1123 imageInfo = ImageInfo.NewInstance(uri, 0);
1124 }
1125 } catch (Exception e) {
1126 String message = "An error occurred when trying to read image meta data for " + uri.toString() + ": " + e.getMessage();
1127 logger.warn(message);
1128 fireWarningEvent(message, "unknown location", 2, 0);
1129 }
1130 ImageFile imageFile = ImageFile.NewInstance(uri, null, imageInfo);
1131 MediaRepresentation representation = MediaRepresentation.NewInstance();
1132 if(imageInfo != null){
1133 representation.setMimeType(imageInfo.getMimeType());
1134 representation.setSuffix(imageInfo.getSuffix());
1135 }
1136 representation.addRepresentationPart(imageFile);
1137 Media media = isFigure ? Figure.NewInstance() : Media.NewInstance();
1138 media.addRepresentation(representation);
1139 return media;
1140 } catch (URISyntaxException e1) {
1141 String message = "An URISyntaxException occurred when trying to create uri from multimedia objcet string: " + uriString;
1142 logger.warn(message);
1143 fireWarningEvent(message, "unknown location", 4, 0);
1144 return null;
1145 }
1146 }
1147 }
1148
1149
1150 /**
1151 * Retrieves an Integer value from a result set. If the value is NULL null is returned.
1152 * ResultSet.getInt() returns 0 therefore we need a special handling for this case.
1153 * @param rs
1154 * @param columnName
1155 * @return
1156 * @throws SQLException
1157 */
1158 protected Integer nullSafeInt(ResultSet rs, String columnName) throws SQLException {
1159 Object intObject = rs.getObject(columnName);
1160 if (intObject == null){
1161 return null;
1162 }else{
1163 return Integer.valueOf(intObject.toString());
1164 }
1165 }
1166
1167 protected Double nullSafeDouble(ResultSet rs, String columnName) throws SQLException {
1168 Object doubleObject = rs.getObject(columnName);
1169 if (doubleObject == null){
1170 return null;
1171 }else{
1172 return Double.valueOf(doubleObject.toString());
1173 }
1174 }
1175
1176 protected Float nullSafeFloat(ResultSet rs, String columnName) throws SQLException {
1177 Object doubleObject = rs.getObject(columnName);
1178 if (doubleObject == null){
1179 return null;
1180 }else{
1181 return Float.valueOf(doubleObject.toString());
1182 }
1183 }
1184
1185
1186 /**
1187 * Returns <code>null</code> for all blank strings. Identity function otherwise.
1188 * @param str
1189 * @return
1190 */
1191 protected String NB(String str) {
1192 if (StringUtils.isBlank(str)){
1193 return null;
1194 }else{
1195 return str;
1196 }
1197 }
1198
1199
1200 }