Project

General

Profile

Download (25.2 KB) Statistics
| Branch: | Tag: | Revision:
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.HashSet;
18
import java.util.List;
19
import java.util.Set;
20
import java.util.UUID;
21

    
22
import org.apache.log4j.Logger;
23

    
24
import eu.etaxonomy.cdm.api.service.pager.Pager;
25
import eu.etaxonomy.cdm.common.CdmUtils;
26
import eu.etaxonomy.cdm.common.media.ImageInfo;
27
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
28
import eu.etaxonomy.cdm.io.common.mapping.IInputTransformer;
29
import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
30
import eu.etaxonomy.cdm.model.common.AnnotationType;
31
import eu.etaxonomy.cdm.model.common.CdmBase;
32
import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
33
import eu.etaxonomy.cdm.model.common.ExtensionType;
34
import eu.etaxonomy.cdm.model.common.IOriginalSource;
35
import eu.etaxonomy.cdm.model.common.ISourceable;
36
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
37
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
38
import eu.etaxonomy.cdm.model.common.Language;
39
import eu.etaxonomy.cdm.model.common.MarkerType;
40
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
41
import eu.etaxonomy.cdm.model.common.TermVocabulary;
42
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
43
import eu.etaxonomy.cdm.model.description.Feature;
44
import eu.etaxonomy.cdm.model.description.PresenceTerm;
45
import eu.etaxonomy.cdm.model.description.TaxonDescription;
46
import eu.etaxonomy.cdm.model.location.NamedArea;
47
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
48
import eu.etaxonomy.cdm.model.location.NamedAreaType;
49
import eu.etaxonomy.cdm.model.location.ReferenceSystem;
50
import eu.etaxonomy.cdm.model.media.ImageFile;
51
import eu.etaxonomy.cdm.model.media.Media;
52
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
53
import eu.etaxonomy.cdm.model.name.NonViralName;
54
import eu.etaxonomy.cdm.model.name.Rank;
55
import eu.etaxonomy.cdm.model.reference.Reference;
56
import eu.etaxonomy.cdm.model.taxon.Classification;
57
import eu.etaxonomy.cdm.model.taxon.Synonym;
58
import eu.etaxonomy.cdm.model.taxon.Taxon;
59
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
60

    
61
/**
62
 * @author a.mueller
63
 * @created 01.07.2008
64
 * @version 1.0
65
 */
66
public abstract class CdmImportBase<CONFIG extends IImportConfigurator, STATE extends ImportStateBase> extends CdmIoBase<STATE> implements ICdmImport<CONFIG, STATE>{
67
	private static Logger logger = Logger.getLogger(CdmImportBase.class);
68
	
69
	protected static final boolean CREATE = true;
70
	protected static final boolean IMAGE_GALLERY = true;
71

    
72
	public static final UUID uuidUserDefinedNamedAreaLevelVocabulary = UUID.fromString("255144da-8d95-457e-a327-9752a8f85e5a");
73
	public static final UUID uuidUserDefinedNamedAreaVocabulary = UUID.fromString("b2238399-a3af-4f6d-b7eb-ff5d0899bf1b");
74
	public static final UUID uuidUserDefinedExtensionTypeVocabulary = UUID.fromString("e28c1394-1be8-4847-8b81-ab44eb6d5bc8");
75
	public static final UUID uuidUserDefinedReferenceSystemVocabulary = UUID.fromString("467591a3-10b4-4bf1-9239-f06ece33e90a");
76
	
77
	private static final String UuidOnly = "UUIDOnly";
78
	private static final String UuidLabel = "UUID or label";
79
	private static final String UuidLabelAbbrev = "UUID, label or abbreviation";
80
	private static final String UuidAbbrev = "UUID or abbreviation";
81
	
82
	public enum TermMatchMode{
83
		UUID_ONLY(0, UuidOnly)
84
		,UUID_LABEL(1, UuidLabel)
85
		,UUID_LABEL_ABBREVLABEL(2, UuidLabelAbbrev)
86
		,UUID_ABBREVLABEL(3, UuidAbbrev)
87
		;
88
		
89
		
90
		private int id;
91
		private String representation;
92
		private TermMatchMode(int id, String representation){
93
			this.id = id;
94
			this.representation = representation;
95
		}
96
		public int getId() {
97
			return id;
98
		}
99
		public String getRepresentation() {
100
			return representation;
101
		}
102
		public TermMatchMode valueOf(int id){
103
			switch (id){
104
				case 0: return UUID_ONLY;
105
				case 1: return UUID_LABEL;
106
				case 2: return UUID_LABEL_ABBREVLABEL;
107
				case 3: return UUID_ABBREVLABEL;
108
				default: return UUID_ONLY;
109
			}
110
 		}
111
		
112
		
113
	}
114
	
115
	protected Classification makeTree(STATE state, Reference reference){
116
		Reference ref = CdmBase.deproxy(reference, Reference.class);
117
		String treeName = "Classification (Import)";
118
		if (ref != null && CdmUtils.isNotEmpty(ref.getTitleCache())){
119
			treeName = ref.getTitleCache();
120
		}
121
		Classification tree = Classification.NewInstance(treeName);
122
		tree.setReference(ref);
123
		
124

    
125
		// use defined uuid for first tree
126
		CONFIG config = (CONFIG)state.getConfig();
127
		if (state.countTrees() < 1 ){
128
			tree.setUuid(config.getClassificationUuid());
129
		}
130
		getClassificationService().save(tree);
131
		state.putTree(ref, tree);
132
		return tree;
133
	}
134
	
135
	
136
	/**
137
	 * Alternative memory saving method variant of
138
	 * {@link #makeTree(STATE state, Reference ref)} which stores only the
139
	 * UUID instead of the full tree in the <code>ImportStateBase</code> by 
140
	 * using <code>state.putTreeUuid(ref, tree);</code>
141
	 * 
142
	 * @param state
143
	 * @param ref
144
	 * @return
145
	 */
146
	protected Classification makeTreeMemSave(STATE state, Reference ref){
147
		String treeName = "Classification (Import)";
148
		if (ref != null && CdmUtils.isNotEmpty(ref.getTitleCache())){
149
			treeName = ref.getTitleCache();
150
		}
151
		Classification tree = Classification.NewInstance(treeName);
152
		tree.setReference(ref);
153
		
154

    
155
		// use defined uuid for first tree
156
		CONFIG config = (CONFIG)state.getConfig();
157
		if (state.countTrees() < 1 ){
158
			tree.setUuid(config.getClassificationUuid());
159
		}
160
		getClassificationService().save(tree);
161
		state.putTreeUuid(ref, tree);
162
		return tree;
163
	}
164
	
165
	
166
	protected ExtensionType getExtensionType(STATE state, UUID uuid, String label, String text, String labelAbbrev){
167
		return getExtensionType(state, uuid, label, text, labelAbbrev, null);
168
	}
169
	protected ExtensionType getExtensionType(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary voc){
170
		if (uuid == null){
171
			uuid = UUID.randomUUID();
172
		}
173
		ExtensionType extensionType = state.getExtensionType(uuid);
174
		if (extensionType == null){
175
			extensionType = (ExtensionType)getTermService().find(uuid);
176
			if (extensionType == null){
177
				extensionType = ExtensionType.NewInstance(text, label, labelAbbrev);
178
				extensionType.setUuid(uuid);
179
				if (voc == null){
180
					boolean isOrdered = false;
181
					voc = getVocabulary(uuidUserDefinedExtensionTypeVocabulary, "User defined vocabulary for extension types", "User Defined Extension Types", null, null, isOrdered);
182
				}
183
				voc.addTerm(extensionType);
184
				getTermService().save(extensionType);
185
			}
186
			state.putExtensionType(extensionType);
187
		}
188
		return extensionType;
189
	}
190
	
191
	
192
	protected MarkerType getMarkerType(STATE state, String keyString) {
193
		IInputTransformer transformer = state.getTransformer();
194
		MarkerType markerType = null;
195
		try {
196
			markerType = transformer.getMarkerTypeByKey(keyString);
197
		} catch (UndefinedTransformerMethodException e) {
198
			logger.info("getMarkerTypeByKey not yet implemented for this import");
199
		}
200
		if (markerType == null ){
201
			UUID uuid;
202
			try {
203
				uuid = transformer.getMarkerTypeUuid(keyString);
204
				return getMarkerType(state, uuid, keyString, keyString, keyString);
205
			} catch (UndefinedTransformerMethodException e) {
206
				logger.warn("getMarkerTypeUuid not yet implemented for this import");
207
			}
208
		}
209
		return null;
210
	}
211
	
212
	protected MarkerType getMarkerType(STATE state, UUID uuid, String label, String text, String labelAbbrev){
213
		if (uuid == null){
214
			uuid = UUID.randomUUID();
215
		}
216
		MarkerType markerType = state.getMarkerType(uuid);
217
		if (markerType == null){
218
			markerType = (MarkerType)getTermService().find(uuid);
219
			if (markerType == null){
220
				markerType = MarkerType.NewInstance(label, text, labelAbbrev);
221
				markerType.setUuid(uuid);
222
				UUID uuidMarkerTypeVoc = UUID.fromString("19dffff7-e142-429c-a420-5d28e4ebe305");
223
				TermVocabulary voc = getVocabularyService().find(uuidMarkerTypeVoc);
224
				voc.addTerm(markerType);
225
				getTermService().save(markerType);
226
			}
227
			state.putMarkerType(markerType);
228
		}
229
		return markerType;
230
	}
231
	
232
	protected AnnotationType getAnnotationType(STATE state, UUID uuid, String label, String text, String labelAbbrev){
233
		if (uuid == null){
234
			uuid = UUID.randomUUID();
235
		}
236
		AnnotationType annotationType = state.getAnnotationType(uuid);
237
		if (annotationType == null){
238
			annotationType = (AnnotationType)getTermService().find(uuid);
239
			if (annotationType == null){
240
				annotationType = AnnotationType.NewInstance(label, text, labelAbbrev);
241
				annotationType.setUuid(uuid);
242
				UUID uuidAnnotationTypeVoc = UUID.fromString("ca04609b-1ba0-4d31-9c2e-aa8eb2f4e62d");
243
				TermVocabulary voc = getVocabularyService().find(uuidAnnotationTypeVoc);
244
				voc.addTerm(annotationType);
245
				getTermService().save(annotationType);
246
			}
247
			state.putAnnotationType(annotationType);
248
		}
249
		return annotationType;
250
	}
251
	
252
	
253
	protected ReferenceSystem getReferenceSystem(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary voc){
254
		if (uuid == null){
255
			uuid = UUID.randomUUID();
256
		}
257
		ReferenceSystem refSystem = state.getReferenceSystem(uuid);
258
		if (refSystem == null){
259
			refSystem = (ReferenceSystem)getTermService().find(uuid);
260
			if (refSystem == null){
261
				refSystem = ReferenceSystem.NewInstance(text, label, labelAbbrev);
262
				if (voc == null){
263
					boolean isOrdered = false;
264
					voc = getVocabulary(uuidUserDefinedReferenceSystemVocabulary, "User defined vocabulary for named areas", "User Defined Reference System", null, null, isOrdered);
265
				}
266
				voc.addTerm(refSystem);
267
				refSystem.setUuid(uuid);
268
				getTermService().save(refSystem);
269
			}
270
			state.putReferenceSystem(refSystem);
271
		}
272
		return refSystem;
273
		
274
	}
275
	
276
	/**
277
	 * Returns a named area for a given uuid by first . If the named area does not
278
	 * @param state
279
	 * @param uuid
280
	 * @param label
281
	 * @param text
282
	 * @param labelAbbrev
283
	 * @param areaType
284
	 * @param level
285
	 * @return
286
	 */
287
	protected NamedArea getNamedArea(STATE state, UUID uuid, String label, String text, String labelAbbrev, NamedAreaType areaType, NamedAreaLevel level){
288
		return getNamedArea(state, uuid, label, text, labelAbbrev, areaType, level, null, null);
289
	}
290

    
291
	protected NamedArea getNamedArea(STATE state, UUID uuid, String label, String text, String labelAbbrev, NamedAreaType areaType, NamedAreaLevel level, TermVocabulary voc, TermMatchMode matchMode){
292
		if (uuid == null){
293
			uuid = UUID.randomUUID();
294
		}
295
		if (matchMode == null){
296
			matchMode = TermMatchMode.UUID_ONLY;
297
		}
298
		NamedArea namedArea = state.getNamedArea(uuid);
299
		if (namedArea == null){
300
			//TODO matching still experimental
301
			namedArea = (NamedArea)getTermService().find(uuid);
302
			if (namedArea == null && matchMode.equals(TermMatchMode.UUID_LABEL)){
303
				logger.warn("UUID_LABEL not yet implemented");
304
			}
305
			if (namedArea == null && matchMode.equals(TermMatchMode.UUID_ABBREVLABEL)){
306
				Pager<NamedArea> areaPager = getTermService().findByRepresentationAbbreviation(labelAbbrev, NamedArea.class, null, null);
307
				namedArea = findBestMatchingArea(areaPager, uuid, label, text, labelAbbrev, areaType, level, voc);
308
			}
309
			if (namedArea == null && matchMode.equals(TermMatchMode.UUID_LABEL_ABBREVLABEL)){
310
				logger.warn("UUID_LABEL not yet implemented");
311
			}
312
			
313
			if (namedArea == null){
314
				namedArea = NamedArea.NewInstance(text, label, labelAbbrev);
315
				if (voc == null){
316
					boolean isOrdered = true;
317
					voc = getVocabulary(uuidUserDefinedNamedAreaVocabulary, "User defined vocabulary for named areas", "User Defined Named Areas", null, null, isOrdered);
318
				}
319
				voc.addTerm(namedArea);
320
				namedArea.setType(areaType);
321
				namedArea.setLevel(level);
322
				namedArea.setUuid(uuid);
323
				getTermService().save(namedArea);
324
			}
325
			state.putNamedArea(namedArea);
326
		}
327
		return namedArea;
328
	}
329
	
330
	
331
	private NamedArea findBestMatchingArea(Pager<NamedArea> areaPager, UUID uuid, String label, String text, String abbrev,
332
			NamedAreaType areaType, NamedAreaLevel level, TermVocabulary voc) {
333
		// TODO preliminary implementation
334
		List<NamedArea> list = areaPager.getRecords();
335
		if (list.size() == 0){
336
			return null;
337
		}else if (list.size() == 1){
338
			return list.get(0);
339
		}else if (list.size() > 1){
340
			String message = "There is more than 1 matching area for %s, %s, %s. As a preliminary implementation I take the first";
341
			message = String.format(message, label, abbrev, text);
342
			logger.warn(message);
343
			return list.get(0);
344
		}
345
		return null;
346
	}
347

    
348

    
349
	protected NamedAreaLevel getNamedAreaLevel(STATE state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<NamedAreaLevel> voc){
350
		if (uuid == null){
351
			uuid = UUID.randomUUID();
352
		}
353
		NamedAreaLevel namedAreaLevel = state.getNamedAreaLevel(uuid);
354
		if (namedAreaLevel == null){
355
			namedAreaLevel = CdmBase.deproxy(getTermService().find(uuid), NamedAreaLevel.class);
356
			if (namedAreaLevel == null){
357
				namedAreaLevel = NamedAreaLevel.NewInstance(text, label, labelAbbrev);
358
				if (voc == null){
359
					boolean isOrdered = true;
360
					voc = getVocabulary(uuidUserDefinedNamedAreaLevelVocabulary, "User defined vocabulary for named area levels", "User Defined Named Area Levels", null, null, isOrdered);
361
				}
362
				voc.addTerm(namedAreaLevel);
363
				namedAreaLevel.setUuid(uuid);
364
				getTermService().save(namedAreaLevel);
365
			}
366
			state.putNamedAreaLevel(namedAreaLevel);
367
		}
368
		return namedAreaLevel;
369
	}
370
	
371
	
372
	protected Feature getFeature(STATE state, UUID uuid){
373
		return getFeature(state, uuid, null, null, null);
374
	}
375
	
376
	/**
377
	 * Returns a feature for a given uuid by first checking if the uuid has already been used in this import, if not
378
	 * checking if the feature exists in the database, if not creating it anew (with vocabulary etc.).
379
	 * If label, text and labelAbbrev are all <code>null</code> no feature is created.
380
	 * @param state
381
	 * @param uuid
382
	 * @param label
383
	 * @param text
384
	 * @param labelAbbrev
385
	 * @return
386
	 */
387
	protected Feature getFeature(STATE state, UUID uuid, String label, String text, String labelAbbrev){
388
		if (uuid == null){
389
			return null;
390
		}
391
		Feature feature = state.getFeature(uuid);
392
		if (feature == null){
393
			feature = (Feature)getTermService().find(uuid);
394
			if (feature == null && ! hasNoLabel(label, text, labelAbbrev)){
395
				feature = Feature.NewInstance(text, label, labelAbbrev);
396
				feature.setUuid(uuid);
397
				feature.setSupportsTextData(true);
398
				//set vocabulary ; FIXME use another user-defined vocabulary
399
				UUID uuidFeatureVoc = UUID.fromString("b187d555-f06f-4d65-9e53-da7c93f8eaa8"); 
400
				TermVocabulary<Feature> voc = getVocabularyService().find(uuidFeatureVoc);
401
				voc.addTerm(feature);
402
				getTermService().save(feature);
403
			}
404
			state.putFeature(feature);
405
		}
406
		return feature;
407
	}
408
	
409
	private boolean hasNoLabel(String label, String text, String labelAbbrev) {
410
		return label == null && text == null && labelAbbrev == null;
411
	}
412

    
413

    
414
	/**
415
	 * Returns a presence term for a given uuid by first ...
416
	 * @param state
417
	 * @param uuid
418
	 * @param label
419
	 * @param text
420
	 * @param labelAbbrev
421
	 * @return
422
	 */
423
	protected PresenceTerm getPresenceTerm(STATE state, UUID uuid, String label, String text, String labelAbbrev){
424
		if (uuid == null){
425
			return null;
426
		}
427
		PresenceTerm presenceTerm = state.getPresenceTerm(uuid);
428
		if (presenceTerm == null){
429
			presenceTerm = (PresenceTerm)getTermService().find(uuid);
430
			if (presenceTerm == null){
431
				presenceTerm = PresenceTerm.NewInstance(text, label, labelAbbrev);
432
				presenceTerm.setUuid(uuid);
433
				//set vocabulary ; FIXME use another user-defined vocabulary
434
				UUID uuidPresenceVoc = UUID.fromString("adbbbe15-c4d3-47b7-80a8-c7d104e53a05"); 
435
				TermVocabulary<PresenceTerm> voc = getVocabularyService().find(uuidPresenceVoc);
436
				voc.addTerm(presenceTerm);
437
				getTermService().save(presenceTerm);
438
			}
439
			state.putPresenceTerm(presenceTerm);
440
		}
441
		return presenceTerm;
442
	}
443

    
444
	/**
445
	 * Returns a language for a given uuid by first ...
446
	 * @param state
447
	 * @param uuid
448
	 * @param label
449
	 * @param text
450
	 * @param labelAbbrev
451
	 * @return
452
	 */
453
	protected Language getLanguage(STATE state, UUID uuid, String label, String text, String labelAbbrev){
454
		if (uuid == null){
455
			return null;
456
		}
457
		Language language = state.getLanguage(uuid);
458
		if (language == null){
459
			language = (Language)getTermService().find(uuid);
460
			if (language == null){
461
				language = Language.NewInstance(text, label, labelAbbrev);
462
				
463
				language.setUuid(uuid);
464
				//set vocabulary ; FIXME use another user-defined vocabulary
465
				UUID uuidLanguageVoc = UUID.fromString("45ac7043-7f5e-4f37-92f2-3874aaaef2de"); 
466
				TermVocabulary<Language> voc = getVocabularyService().find(uuidLanguageVoc);
467
				voc.addTerm(language);
468
				getTermService().save(language);
469
			}
470
			state.putLanguage(language);
471
		}
472
		return language;
473
	}
474
	
475

    
476
	/**
477
	 * @param uuid 
478
	 * @return
479
	 * 
480
	 */
481
	protected TermVocabulary getVocabulary(UUID uuid, String text, String label, String abbrev, URI termSourceUri, boolean isOrdered) {
482
		TermVocabulary voc = getVocabularyService().find(uuid);
483
		if (voc == null){
484
			if (isOrdered){
485
				voc = OrderedTermVocabulary.NewInstance(text, label, abbrev, termSourceUri);
486
			}else{
487
				voc = TermVocabulary.NewInstance(text, label, abbrev, termSourceUri);
488
			}
489
			voc.setUuid(uuid);
490
			getVocabularyService().save(voc);
491
		}
492
		return voc;
493
	}
494
	
495
	/**
496
	 * Adds an orginal source to a sourceable objects (implemented for Identifiable entity and description element.
497
	 * If cdmBase is not sourceable nothing happens.
498
	 * TODO Move to DbImportBase once this exists.
499
	 * TODO also implemented in DbImportObjectCreationMapper (reduce redundance)
500
	 * @param rs
501
	 * @param cdmBase
502
	 * @param dbIdAttribute
503
	 * @param namespace
504
	 * @param citation
505
	 * @throws SQLException
506
	 */
507
	public void addOriginalSource(CdmBase cdmBase, Object idAttributeValue, String namespace, Reference citation)  {
508
		if (cdmBase instanceof ISourceable ){
509
			IOriginalSource source;
510
			ISourceable sourceable = (ISourceable)cdmBase;
511
			Object id = idAttributeValue;
512
			String strId = String.valueOf(id);
513
			String microCitation = null;
514
			if (cdmBase instanceof IdentifiableEntity){
515
				source = IdentifiableSource.NewInstance(strId, namespace, citation, microCitation);
516
			}else if (cdmBase instanceof DescriptionElementBase){
517
				source = DescriptionElementSource.NewInstance(strId, namespace, citation, microCitation);
518
			}else{
519
				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.");
520
				return;
521
			}
522
			sourceable.addSource(source);
523
		}else if (cdmBase != null){
524
			logger.warn("Sourced object does not implement ISourceable: " + cdmBase.getClass() + "," + cdmBase.getUuid());
525
		}else{
526
			logger.warn("Sourced object is null");
527
		}
528
	}
529
	
530
	/**
531
	 * @see #addOriginalSource(CdmBase, Object, String, Reference)
532
	 * @param rs
533
	 * @param cdmBase
534
	 * @param dbIdAttribute
535
	 * @param namespace
536
	 * @param citation
537
	 * @throws SQLException
538
	 */
539
	public void addOriginalSource(ResultSet rs, CdmBase cdmBase, String dbIdAttribute, String namespace, Reference citation) throws SQLException {
540
		Object id = rs.getObject(dbIdAttribute);
541
		addOriginalSource(cdmBase, id, namespace, citation);
542
	}
543
	
544

    
545
	/**
546
	 * If the child taxon is missing genus or species epithet information and the rank is below <i>genus</i>
547
	 * or <i>species</i> respectively the according epithets are taken from the parent taxon.
548
	 * If the name is an autonym and has no combination author/basionym author the authors are taken from
549
	 * the parent.
550
	 * @param parentTaxon
551
	 * @param childTaxon
552
	 */
553
	protected void fillMissingEpithetsForTaxa(Taxon parentTaxon, Taxon childTaxon) {
554
		NonViralName parentName = HibernateProxyHelper.deproxy(parentTaxon.getName(), NonViralName.class);
555
		NonViralName childName = HibernateProxyHelper.deproxy(childTaxon.getName(), NonViralName.class);
556
		fillMissingEpithets(parentName, childName);
557
	}
558
	
559
	/**
560
	 * If the child name is missing genus or species epithet information and the rank is below <i>genus</i>
561
	 * or <i>species</i> respectively the according epithets are taken from the parent name.
562
	 * If the name is an autonym and has no combination author/basionym author the authors are taken from
563
	 * the parent.
564
	 * @param parentTaxon
565
	 * @param childTaxon
566
	 */
567
	protected void fillMissingEpithets(NonViralName parentName, NonViralName childName) {
568
		if (CdmUtils.isEmpty(childName.getGenusOrUninomial()) && childName.getRank().isLower(Rank.GENUS()) ){
569
			childName.setGenusOrUninomial(parentName.getGenusOrUninomial());
570
		}
571
		
572
		if (CdmUtils.isEmpty(childName.getSpecificEpithet()) && childName.getRank().isLower(Rank.SPECIES()) ){
573
			childName.setSpecificEpithet(parentName.getSpecificEpithet());
574
		}
575
		if (childName.isAutonym() && childName.getCombinationAuthorTeam() == null && childName.getBasionymAuthorTeam() == null ){
576
			childName.setCombinationAuthorTeam(parentName.getCombinationAuthorTeam());
577
			childName.setBasionymAuthorTeam(parentName.getBasionymAuthorTeam());
578
		}	
579
	}
580
	
581
	/**
582
	 * Returns the taxon description for a taxon. If there are multiple taxon descriptions
583
	 * an arbitrary one is chosen.
584
	 * If no taxon description exists, a new one is created if <code>createNewIfNotExists</code>
585
	 * is <code>true</code>.
586
	 * @param createNewIfNotExists
587
	 * @param isImageGallery if true only taxon description being image galleries are considered.
588
	 * If false only taxon description being no image galleries are considered.
589
	 * @return
590
	 */
591
	public TaxonDescription getTaxonDescription(Taxon taxon, boolean isImageGallery, boolean createNewIfNotExists) {
592
		TaxonDescription result = null;
593
		Set<TaxonDescription> descriptions= taxon.getDescriptions();
594
		for (TaxonDescription description : descriptions){
595
			if (description.isImageGallery() == isImageGallery){
596
				result = description;
597
				break;
598
			}
599
		}
600
		if (result == null && createNewIfNotExists){
601
			result = TaxonDescription.NewInstance(taxon);
602
			result.setImageGallery(isImageGallery);
603
		}
604
		return result;
605
	}
606
	
607
	
608
	/**
609
	 * Returns the accepted taxon of a {@link TaxonBase taxon base}. <BR>
610
	 * If taxonBase is of type taxon the same object is returned. If taxonBase is of type
611
	 * synonym the accepted taxon is returned if one exists. If no accepted taxon exists
612
	 * <code>null</code> is returned. If multiple accepted taxa exist the one taxon with the 
613
	 * same secundum reference is returned. If no such single taxon exists an 
614
	 * {@link IllegalStateException illegal state exception} is thrown.  
615
	 * @param taxonBase
616
	 * @return
617
	 */
618
	protected Taxon getAcceptedTaxon(TaxonBase<?> taxonBase) {
619
		if (taxonBase == null){
620
			return null;
621
		}else if(taxonBase.isInstanceOf(Taxon.class)){
622
			return CdmBase.deproxy(taxonBase, Taxon.class);
623
		}else if(taxonBase.isInstanceOf(Synonym.class)){
624
			Synonym synonym = CdmBase.deproxy(taxonBase, Synonym.class);
625
			Set<Taxon> acceptedTaxa = synonym.getAcceptedTaxa();
626
			if (acceptedTaxa.size() == 0){
627
				return null;
628
			}else if (acceptedTaxa.size() == 1){
629
				return acceptedTaxa.iterator().next();
630
			}else{
631
				Reference sec = synonym.getSec();
632
				if (sec != null){
633
					Set<Taxon> taxaWithSameSec = new HashSet<Taxon>();
634
					for (Taxon taxon: acceptedTaxa){
635
						if (sec.equals(taxon.getSec())){
636
							taxaWithSameSec.add(taxon);
637
						}
638
					}
639
					if (taxaWithSameSec.size() == 1){
640
						return taxaWithSameSec.iterator().next();
641
					}
642
				}
643
				throw new IllegalStateException("Can't define the one accepted taxon for a synonym out of multiple accept taxa");
644
			}
645
		}else{
646
			throw new IllegalStateException("Unknown TaxonBase subclass: " + taxonBase.getClass().getName());
647
		}
648
	}
649

    
650
	
651

    
652
	/**
653
	 * @param derivedUnitFacade
654
	 * @param multimediaObject
655
	 * @throws MalformedURLException
656
	 */
657
	protected Media getImageMedia(String multimediaObject, boolean readDataFromUrl) throws MalformedURLException {
658
		if( multimediaObject == null){
659
			return null;
660
		} else {
661
			ImageInfo imageInfo = null;
662
			URI uri;
663
			try {
664
				uri = new URI(multimediaObject);
665
				try {
666
					if (readDataFromUrl){
667
						imageInfo = ImageInfo.NewInstance(uri, 0);
668
					}
669
				} catch (Exception e) {
670
					String message = "An error occurred when trying to read image meta data: " +  e.getMessage();
671
					logger.warn(message);
672
				}
673
				ImageFile imageFile = ImageFile.NewInstance(uri, null, imageInfo);
674
				MediaRepresentation representation = MediaRepresentation.NewInstance();
675
				if(imageInfo != null){
676
					representation.setMimeType(imageInfo.getMimeType());
677
				}
678
				representation.addRepresentationPart(imageFile);
679
				Media media = Media.NewInstance();
680
				media.addRepresentation(representation);
681
				return media;
682
			} catch (URISyntaxException e1) {
683
				String message = "An URISyntaxException occurred when trying to create uri from multimedia objcet string: " +  multimediaObject;
684
				logger.warn(message);
685
				return null;
686
			}
687
		}
688
	}
689

    
690
	
691
}
(9-9/48)