Project

General

Profile

Download (52.7 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.sdd.out;
11

    
12
import java.io.File;
13
import java.io.FileOutputStream;
14
import java.io.IOException;
15
import java.io.OutputStream;
16
import java.io.OutputStreamWriter;
17
import java.io.Writer;
18
import java.time.ZonedDateTime;
19
import java.time.format.DateTimeFormatter;
20
import java.util.HashMap;
21
import java.util.HashSet;
22
import java.util.Iterator;
23
import java.util.List;
24
import java.util.Map;
25
import java.util.Set;
26

    
27
import javax.xml.bind.Marshaller;
28

    
29
import org.apache.log4j.Logger;
30
import org.apache.xerces.dom.DocumentImpl;
31
import org.apache.xerces.dom.ElementImpl;
32
import org.apache.xerces.impl.xpath.regex.ParseException;
33
import org.apache.xml.serialize.DOMSerializer;
34
import org.apache.xml.serialize.OutputFormat;
35
import org.apache.xml.serialize.XMLSerializer;
36
import org.springframework.util.ResourceUtils;
37
import org.xml.sax.SAXException;
38

    
39
import eu.etaxonomy.cdm.io.jaxb.CdmMarshallerListener;
40
import eu.etaxonomy.cdm.model.agent.AgentBase;
41
import eu.etaxonomy.cdm.model.agent.Person;
42
import eu.etaxonomy.cdm.model.agent.Team;
43
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
44
import eu.etaxonomy.cdm.model.common.Annotation;
45
import eu.etaxonomy.cdm.model.common.AnnotationType;
46
import eu.etaxonomy.cdm.model.common.DefinedTerm;
47
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
48
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
49
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
50
import eu.etaxonomy.cdm.model.common.Language;
51
import eu.etaxonomy.cdm.model.common.LanguageString;
52
import eu.etaxonomy.cdm.model.common.Marker;
53
import eu.etaxonomy.cdm.model.common.Representation;
54
import eu.etaxonomy.cdm.model.common.TermBase;
55
import eu.etaxonomy.cdm.model.common.TermVocabulary;
56
import eu.etaxonomy.cdm.model.common.VersionableEntity;
57
import eu.etaxonomy.cdm.model.description.CategoricalData;
58
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
59
import eu.etaxonomy.cdm.model.description.Feature;
60
import eu.etaxonomy.cdm.model.description.FeatureNode;
61
import eu.etaxonomy.cdm.model.description.FeatureTree;
62
import eu.etaxonomy.cdm.model.description.QuantitativeData;
63
import eu.etaxonomy.cdm.model.description.State;
64
import eu.etaxonomy.cdm.model.description.StateData;
65
import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
66
import eu.etaxonomy.cdm.model.description.StatisticalMeasurementValue;
67
import eu.etaxonomy.cdm.model.description.TaxonDescription;
68
import eu.etaxonomy.cdm.model.description.TextData;
69
import eu.etaxonomy.cdm.model.location.NamedArea;
70
import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
71
import eu.etaxonomy.cdm.model.media.Media;
72
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
73
import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
74
import eu.etaxonomy.cdm.model.media.Rights;
75
import eu.etaxonomy.cdm.model.name.TaxonName;
76
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
77
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
78
import eu.etaxonomy.cdm.model.reference.IDatabase;
79
import eu.etaxonomy.cdm.model.reference.Reference;
80
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
81
import eu.etaxonomy.cdm.model.reference.ReferenceType;
82
import eu.etaxonomy.cdm.model.taxon.Taxon;
83
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
84
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
85

    
86
/**
87
 * Writes the SDD XML file.
88
 *
89
 * @author h.fradin
90
 * @created 10.12.2008
91
 * @version 1.0
92
 */
93

    
94
public class SDDDocumentBuilder {
95

    
96
	private final DocumentImpl document;
97
	private XMLSerializer xmlserializer;
98
	private Writer writer;
99
	private DOMSerializer domi;
100
	private SDDDataSet cdmSource;
101

    
102
	private final Map<Person, String> agents = new HashMap<>();
103
	private final Map<TaxonName, String> taxonNames = new HashMap<>();
104
	private final Map<Feature, String> characters = new HashMap<>();
105
	private final Map<FeatureNode, String> featureNodes = new HashMap<>();
106
	private final Map<Feature, String> descriptiveConcepts = new HashMap<>();
107
	private final Map<TaxonDescription, String> codedDescriptions = new HashMap<>();
108
	private final Map<Media, String> medias = new HashMap<>();
109
	private final Map<State, String> states = new HashMap<>();
110
	private final Map<Reference, String> articles = new HashMap<>();
111
	private final Map<VersionableEntity, String> featuretrees = new HashMap<>();
112
	private final Map<DefinedTerm, String> modifiers = new HashMap<>();
113
	private final Map<TaxonNode, String> taxonNodes = new HashMap<>();
114
	private final Map<NamedArea, String> namedAreas = new HashMap<>();
115
	private final Map<DerivedUnit, String> specimens = new HashMap<>();
116

    
117
	private final Map<VersionableEntity, String> features = new HashMap<>();
118
	private int agentsCount = 0;
119
	private int articlesCount = 0;
120
	private int codedDescriptionsCount = 0;
121
	private int taxonNamesCount = 0;
122
	private int charactersCount = 0;
123
	private int textcharactersCount = 0;
124
	private int mediasCount = 0;
125
	private int statesCount = 0;
126
	private final int featureNodesCount = 0;
127
	private int chartreeCount = 0;
128
	private int charnodeCount = 0;
129
	private int taxonNodesCount = 0;
130
	private int namedAreasCount = 0;
131
	private int specimenCount = 0;
132
	private int descriptiveConceptCount = 0;
133
	private int modifiersCount = 0;
134

    
135
	private final String AGENT = "Agent";
136
	private final String AGENTS = "Agents";
137
	private final String CATEGORICAL = "Categorical";
138
	private final String CATEGORICAL_CHARACTER = "CategoricalCharacter";
139
	private final String CHARACTER = "Character";
140
	private final String CHARACTERS = "Characters";
141
	private final String CHARACTER_TREE = "CharacterTree";
142
	private final String CHARACTER_TREES = "CharacterTrees";
143
	private final String CHAR_NODE = "CharNode";
144
	private final String CITATION = "Citation";
145
	private final String CODED_DESCRIPTION = "CodedDescription";
146
	private final String CODED_DESCRIPTIONS = "CodedDescriptions";
147
	private final String CONTENT = "Content";
148
	private final String CREATORS = "Creators";
149
	private final String DATASET = "Dataset";
150
	private final String DATASETS = "Datasets";
151
	private final String DATE_CREATED = "DateCreated";
152
	private final String DATE_MODIFIED = "DateModified";
153
	private final String DEPENDENCY_RULES = "DependencyRules";
154
	private final String DESCRIPTIVE_CONCEPT = "DescriptiveConcept";
155
	private final String DESCRIPTIVE_CONCEPTS = "DescriptiveConcepts";
156
	private final String DETAIL = "Detail";
157
	private final String GENERATOR = "Generator";
158
	private final String ID = "id";
159
	private final String IMAGE = "Image";
160
	private final String INAPPLICABLE_IF = "InapplicableIf";
161
	private final String IPR_STATEMENT = "IPRStatement";
162
	private final String IPR_STATEMENTS = "IPRStatements";
163
	private final String LABEL = "Label";
164
	private final String MEASURE = "Measure";
165
	private final String MEDIA_OBJECT = "MediaObject";
166
	private final String MEDIA_OBJECTS = "MediaObjects";
167
	private final String NODE = "Node";
168
	private final String NODES = "Nodes";
169
	private final String NOTE = "Note";
170
	private final String PARENT = "Parent";
171
	private final String PUBLICATIONS = "Publications";
172
	private final String QUANTITATIVE = "Quantitative";
173
	private final String QUANTITATIVE_CHARACTER = "QuantitativeCharacter";
174
	private final String REF = "ref";
175
	private final String REPRESENTATION = "Representation";
176
	private final String REVISION_DATA = "RevisionData";
177
	private final String ROLE = "role";
178
	private final String SCOPE = "Scope";
179
	private final String SHOULD_CONTAIN_ALL_CHARACTERS = "ShouldContainAllCharacters";
180
	private final String SOURCE = "Source";
181
	private final String STATE = "State";
182
	private final String STATE_DEFINITION = "StateDefinition";
183
	private final String STATES = "States";
184
	private final String STATUS = "Status";
185
	private final String SUMMARY_DATA = "SummaryData";
186
	private final String TAXON_NAME = "TaxonName";
187
	private final String TAXON_NAMES = "TaxonNames";
188
	private final String TECHNICAL_METADATA = "TechnicalMetadata";
189
	private final String TEXT = "text";
190
	private final String TEXT_CHAR = "TextChar";
191
	private final String TEXT_CHARACTER = "TextCharacter";
192
	private final String TYPE = "Type";
193
	private final String URI = "uri";
194

    
195
	private final Language defaultLanguage = Language.DEFAULT();
196

    
197
	private static final Logger logger = Logger
198
			.getLogger(SDDDocumentBuilder.class);
199

    
200
	private final String NEWLINE = System.getProperty("line.separator");
201

    
202
	public SDDDocumentBuilder() throws SAXException, IOException {
203

    
204
		document = new DocumentImpl();
205

    
206
	}
207

    
208
	public void marshal(SDDDataSet cdmSource, File sddDestination)
209
			throws IOException {
210

    
211
		this.cdmSource = cdmSource;
212
		Marshaller marshaller;
213
		CdmMarshallerListener marshallerListener = new CdmMarshallerListener();
214
		logger.info("Start marshalling");
215
		writeCDMtoSDD(sddDestination);
216

    
217
	}
218

    
219
	public void marshal(SDDDataSet cdmSource, String sddDestinationFileName)
220
			throws IOException {
221

    
222
		this.cdmSource = cdmSource;
223
		Marshaller marshaller;
224
		CdmMarshallerListener marshallerListener = new CdmMarshallerListener();
225
		logger.info("Start marshalling");
226
		writeCDMtoSDD(ResourceUtils.getFile(sddDestinationFileName));
227

    
228
	}
229

    
230
    public void marshal(SDDDataSet dataSet, OutputStream stream) throws IOException {
231
        this.cdmSource = dataSet;
232
        logger.info("Start marshalling");
233
        try {
234
            buildDocument();
235
        } catch (ParseException e) {
236
            e.printStackTrace();
237
        }
238

    
239
        OutputFormat format = new OutputFormat(document, "UTF-8", true);
240

    
241
        writer = new OutputStreamWriter(stream, "UTF-8");
242

    
243
        xmlserializer = new XMLSerializer(writer, format);
244
        domi = xmlserializer.asDOMSerializer(); // As a DOM Serializer
245

    
246
        domi.serialize(document.getDocumentElement());
247

    
248
        writer.close();
249
    }
250
	/**
251
	 * Write the DOM document.
252
	 *
253
	 * @param base
254
	 * @throws IOException
255
	 */
256
	public void writeCDMtoSDD(File sddDestination) throws IOException {
257

    
258
		try {
259
			buildDocument();
260
		} catch (ParseException e) {
261
			e.printStackTrace();
262
		}
263

    
264
		OutputFormat format = new OutputFormat(document, "UTF-8", true);
265

    
266
		FileOutputStream fos = new FileOutputStream(sddDestination);
267

    
268
		writer = new OutputStreamWriter(fos, "UTF-8");
269

    
270
		xmlserializer = new XMLSerializer(writer, format);
271
		domi = xmlserializer.asDOMSerializer(); // As a DOM Serializer
272

    
273
		domi.serialize(document.getDocumentElement());
274

    
275
		writer.close();
276
	}
277

    
278
	// #############
279
	// # BUILD DOM #
280
	// #############
281

    
282
	/**
283
	 * Builds the whole document.
284
	 *
285
	 * @param base
286
	 *            the Base
287
	 * @throws ParseException
288
	 */
289
	public void buildDocument() throws ParseException {
290

    
291
		// create <Datasets> = root node
292
		ElementImpl baselement = new ElementImpl(document, DATASETS);
293
		baselement.setAttribute("xmlns:xsi",
294
				"http://www.w3.org/2001/XMLSchema-instance");
295
		baselement.setAttribute("xmlns", "http://rs.tdwg.org/UBIF/2006/");
296
		baselement
297
				.setAttribute("xsi:schemaLocation",
298
						"http://rs.tdwg.org/UBIF/2006 http://rs.tdwg.org/UBIF/2006/Schema/1.1/SDD.xsd");
299

    
300
		buildTechnicalMetadata(baselement);
301

    
302
		List<Reference> references = cdmSource.getReferences();
303
		Iterator<Reference> iterator = references.iterator();
304
		IDatabase d = ReferenceFactory.newDatabase();
305
		while (iterator.hasNext()) {
306
			Reference reference = iterator.next();
307
			if (reference.getType().equals(ReferenceType.Database)) {
308
				buildDataset(baselement, reference);
309
			}
310
		}
311
		document.appendChild(baselement);
312
	}
313

    
314
	// #############
315
	// # BUILD DOM #
316
	// #############
317

    
318
	/**
319
	 * Builds TechnicalMetadata associated with the SDD file
320
	 */
321
	public void buildTechnicalMetadata(ElementImpl baselement)
322
			throws ParseException {
323
		// create TechnicalMetadata
324
		ElementImpl technicalMetadata = new ElementImpl(document,
325
				TECHNICAL_METADATA);
326
		// select different databases associated to different descriptions TODO
327
		List<Reference> references = cdmSource.getReferences();
328
		Iterator<Reference> iterator = references.iterator();
329
		boolean database = false;
330
		IDatabase d = ReferenceFactory.newDatabase();
331
		while ((iterator.hasNext()) && (!database)) {
332
			Reference reference = iterator.next();
333
			if (reference.getType().equals(ReferenceType.Database)) {
334
				d = reference;
335
			}
336
		}
337
		ZonedDateTime dt = d.getCreated();
338
		String date = dt.toString().substring(0, 19);
339
		technicalMetadata.setAttribute("created", date);
340

    
341
		ElementImpl generator = new ElementImpl(document, GENERATOR);
342
		generator.setAttribute("name", "EDIT CDM");
343
		generator.setAttribute("version", "v1");
344
		generator
345
				.setAttribute(
346
						"notes",
347
						"This SDD file has been generated by the SDD export functionality of the EDIT platform for Cybertaxonomy - Copyright (c) 2008");
348
		technicalMetadata.appendChild(generator);
349

    
350
		baselement.appendChild(technicalMetadata);
351
	}
352

    
353
	// Builds the information associated with a dataset
354
	public void buildDataset(ElementImpl baselement, IDatabase reference)
355
			throws ParseException {
356
		// create Dataset and language
357
		ElementImpl dataset = new ElementImpl(document, DATASET);
358
		// no default language associated with a dataset in the CDM
359
		dataset.setAttribute("xml:lang", Language.DEFAULT().getIso639_1());
360
		baselement.appendChild(dataset);
361
		buildRepresentation(dataset, reference);
362
		buildRevisionData(dataset, reference);
363
		buildIPRStatements(dataset, reference);
364
		buildTaxonNames(dataset);
365
		buildDescriptiveConcepts(dataset);
366
		buildCharacters(dataset);
367
		buildCodedDescriptions(dataset);
368
		buildAgents(dataset);
369
		buildPublications(dataset);
370
		buildMediaObjects(dataset);
371
		buildCharacterTrees(dataset);
372
		buildClassifications(dataset);
373
		buildGeographicAreas(dataset);
374
		buildSpecimens(dataset);
375
	}
376

    
377
	/**
378
	 * Builds a Representation element using a Reference
379
	 */
380
	public void buildRepresentation(ElementImpl element, IDatabase reference)
381
			throws ParseException {
382

    
383
		// create <Representation> element
384
		ElementImpl representation = new ElementImpl(document, REPRESENTATION);
385
		element.appendChild(representation);
386
		buildLabel(representation, reference.getTitleCache());
387

    
388
		Set<Annotation> annotations = ((Reference) reference).getAnnotations();
389
		Iterator<Annotation> iterator = annotations.iterator();
390
		String detailText = null;
391
		if (iterator.hasNext()) {
392
			Annotation annotation = iterator.next();
393
			detailText = annotation.getText();
394
		}
395

    
396
		if (detailText != null && !detailText.equals("")) {
397
			ElementImpl detail = new ElementImpl(document, DETAIL);
398
			detail.appendChild(document.createTextNode(detailText));
399
			representation.appendChild(detail);
400
		}
401

    
402
		Set<Media> rm = ((Reference) reference).getMedia();
403

    
404
		if (rm != null && rm.size() > 0) {
405
			ElementImpl mediaObject;
406

    
407
			for (int i = 0; i < rm.size(); i++) {
408
				mediaObject = new ElementImpl(document, MEDIA_OBJECT);
409
				mediasCount = buildReference((Media) rm.toArray()[i], medias,
410
						REF, mediaObject, "m", mediasCount);
411
				representation.appendChild(mediaObject);
412
			}
413
		}
414

    
415
	}
416

    
417
	/**
418
	 * Builds a Representation element using a Feature
419
	 */
420
	public void buildRepresentation(ElementImpl element, TermBase tb)
421
			throws ParseException {
422

    
423
		// create <Representation> element
424
		ElementImpl representation = new ElementImpl(document, REPRESENTATION);
425
		element.appendChild(representation);
426

    
427
		Set<Representation> representations = tb.getRepresentations();
428
		if (representations != null) {
429
			if (!representations.isEmpty()) {
430
				String label = ((Representation) representations.toArray()[0])
431
						.getLabel();
432
				buildLabel(representation, label);
433
				String detailText = tb.getDescription();
434

    
435
				if (detailText != null && !detailText.equals("")) {
436
					if (!detailText.equals(label)) {
437
						ElementImpl detail = new ElementImpl(document, DETAIL);
438
						detail.appendChild(document.createTextNode(detailText));
439
						representation.appendChild(detail);
440
					}
441
				}
442

    
443
			}
444
		}
445

    
446
		if (tb instanceof DefinedTermBase) {
447
			DefinedTermBase dtb = (DefinedTermBase) tb;
448
			Set<Media> rm = dtb.getMedia();
449

    
450
			if (rm != null && rm.size() > 0) {
451
				ElementImpl mediaObject;
452

    
453
				for (int i = 0; i < rm.size(); i++) {
454
					mediaObject = new ElementImpl(document, MEDIA_OBJECT);
455
					mediasCount = buildReference((Media) rm.toArray()[i],
456
							medias, REF, mediaObject, "m", mediasCount);
457
					representation.appendChild(mediaObject);
458
				}
459
			}
460
		}
461
	}
462

    
463
	/**
464
	 * Builds a Representation element using an IdentifiableEntity
465
	 */
466
	public void buildRepresentation(ElementImpl element, IdentifiableEntity ie)
467
			throws ParseException {
468

    
469
		// create <Representation> element
470
		ElementImpl representation = new ElementImpl(document, REPRESENTATION);
471
		element.appendChild(representation);
472
		buildLabel(representation, ie.getTitleCache());
473

    
474
		Set<Annotation> annotations = ie.getAnnotations();
475
		Iterator iterator = annotations.iterator();
476
		String detailText = null;
477
		if (iterator.hasNext()) {
478
			Annotation annotation = (Annotation) iterator.next();
479
			detailText = annotation.getText();
480
		}
481

    
482
		if (detailText != null && !detailText.equals("")) {
483
			ElementImpl detail = new ElementImpl(document, DETAIL);
484
			detail.appendChild(document.createTextNode(detailText));
485
			representation.appendChild(detail);
486
		}
487

    
488
		if (ie instanceof DefinedTermBase) {
489
			DefinedTermBase dtb = (DefinedTermBase) ie;
490
			Set<Media> rm = dtb.getMedia();
491

    
492
			if (rm != null && rm.size() > 0) {
493
				ElementImpl mediaObject;
494

    
495
				for (int i = 0; i < rm.size(); i++) {
496
					mediaObject = new ElementImpl(document, MEDIA_OBJECT);
497
					mediasCount = buildReference((Media) rm.toArray()[i],
498
							medias, REF, mediaObject, "m", mediasCount);
499
					representation.appendChild(mediaObject);
500
				}
501
			}
502
		}
503
		if (ie instanceof IdentifiableMediaEntity) {
504
			IdentifiableMediaEntity ime = (IdentifiableMediaEntity) ie;
505
			Set<Media> medias = ime.getMedia();
506
			if (medias != null) {
507
				ElementImpl elLinks = new ElementImpl(document, "Links");
508
				for (Iterator<Media> m = medias.iterator(); m.hasNext();) {
509
					Media media = m.next();
510
					Set<MediaRepresentation> smr = media.getRepresentations();
511
					for (Iterator<MediaRepresentation> mr = smr.iterator(); mr
512
							.hasNext();) {
513
						MediaRepresentation mediarep = mr.next();
514
						List<MediaRepresentationPart> lmrp = mediarep
515
								.getParts();
516
						for (Iterator<MediaRepresentationPart> mrp = lmrp
517
								.iterator(); mrp.hasNext();) {
518
							MediaRepresentationPart mediareppart = mrp.next();
519
							ElementImpl elLink = new ElementImpl(document,
520
									"Link");
521
							elLink.setAttribute("href", mediareppart.getUri()
522
									.toString());
523
							elLinks.appendChild(elLink);
524
						}
525
					}
526
				}
527
				element.appendChild(elLinks);
528
			}
529
		}
530

    
531
	}
532

    
533
	/**
534
	 * Builds RevisionData associated with the Dataset
535
	 */
536
	public void buildRevisionData(ElementImpl dataset, IDatabase database)
537
			throws ParseException {
538

    
539
		// <RevisionData>
540
		// <Creators>
541
		// <Agent role="aut" ref="a1"/>
542
		// <Agent role="aut" ref="a2"/>
543
		// <Agent role="edt" ref="a3"/>
544
		// </Creators>
545
		// <DateModified>2006-04-08T00:00:00</DateModified>
546
		// </RevisionData>
547

    
548
		ElementImpl revisionData = new ElementImpl(document, REVISION_DATA);
549

    
550
		// authors
551
		TeamOrPersonBase authors = database.getAuthorship();
552
		// TeamOrPersonBase editors = database.getUpdatedBy();
553

    
554
		if ((authors != null)) { // || (editors != null)) {
555
			ElementImpl creators = new ElementImpl(document, CREATORS);
556
			if (authors != null) {
557
				buildRefAgent(creators, authors, "aut");
558
			}
559
			// if (editors != null) {
560
			// buildRefAgent(creators, editors, "edt");
561
			// }
562
			revisionData.appendChild(creators);
563
		}
564

    
565
		buildDateModified(revisionData, database);
566

    
567
		dataset.appendChild(revisionData);
568
	}
569

    
570
	/**
571
	 * Builds ModifiedDate associated with RevisionData
572
	 */
573
	public void buildDateModified(ElementImpl revisionData, IDatabase database)
574
			throws ParseException {
575

    
576
		// <DateModified>2006-04-08T00:00:00</DateModified>
577

    
578
		if (((Reference) database).getUpdated() != null) {
579
			ElementImpl dateModified = new ElementImpl(document, DATE_MODIFIED);
580

    
581
			ZonedDateTime c = ((Reference) database).getUpdated();
582
			DateTimeFormatter fmt = DateTimeFormatter.ISO_DATE_TIME;
583

    
584
			String date = c.format(fmt);
585
			dateModified.appendChild(document.createTextNode(date));
586

    
587
			revisionData.appendChild(dateModified);
588
		}
589

    
590
	}
591

    
592
	/**
593
	 * Builds IPRStatements associated with the Dataset
594
	 */
595
	public void buildIPRStatements(ElementImpl dataset, IDatabase database)
596
			throws ParseException {
597

    
598
		// <IPRStatements>
599
		// <IPRStatement role="Copyright">
600
		// <Label xml:lang="en-au">(c) 2003-2006 Centre for Occasional
601
		// Botany.</Label>
602
		// </IPRStatement>
603
		// </IPRStatements>
604

    
605
		if (database.getRights() != null) {
606
			// create IPRStatements
607
			ElementImpl iprStatements = new ElementImpl(document,
608
					IPR_STATEMENTS);
609
			dataset.appendChild(iprStatements);
610

    
611
			// mapping between IPRStatement Copyright (SDD) and first Right in
612
			// the list of Rights
613
			ElementImpl iprStatement = new ElementImpl(document, IPR_STATEMENT);
614
			iprStatement.setAttribute("role", "Copyright");
615
			iprStatements.appendChild(iprStatement);
616
			if (!database.getRights().isEmpty()) {
617
				buildLabel(iprStatement, ((Rights) database.getRights()
618
						.toArray()[0]).getText());
619
			}
620
		}
621

    
622
	}
623

    
624
	/**
625
	 * Creates a Label element
626
	 *
627
	 * @param base
628
	 * @param element
629
	 */
630
	public void buildLabel(ElementImpl element, String text) {
631
		ElementImpl label = new ElementImpl(document, LABEL);
632
		label.appendChild(document.createTextNode(text));
633
		element.appendChild(label);
634
	}
635

    
636
	// ################
637
	// # GENERIC BRICKS #
638
	// ################
639

    
640
	/**
641
	 * Builds TaxonNames associated with the Dataset
642
	 */
643
	public void buildTaxonNames(ElementImpl dataset) throws ParseException {
644

    
645
		// <TaxonNames>
646
		// <TaxonName id="t1" uri="urn:lsid:authority:namespace:my-own-id">
647
		// <Representation>
648
		// <Label xml:lang="la">Viola hederacea Labill.</Label>
649
		// </Representation>
650
		// </TaxonName>
651
		// </TaxonNames>
652

    
653
		if (cdmSource.getTaxonomicNames() != null) {
654
			ElementImpl elTaxonNames = new ElementImpl(document, TAXON_NAMES);
655

    
656
			for (int i = 0; i < cdmSource.getTaxonomicNames().size(); i++) {
657
				ElementImpl elTaxonName = new ElementImpl(document, TAXON_NAME);
658
				TaxonName tnb = cdmSource.getTaxonomicNames().get(i);
659

    
660
				taxonNamesCount = buildReference(tnb, taxonNames, ID,
661
						elTaxonName, "t", taxonNamesCount);
662

    
663
				buildRepresentation(elTaxonName, tnb);
664

    
665
				elTaxonNames.appendChild(elTaxonName);
666
			}
667

    
668
			dataset.appendChild(elTaxonNames);
669
		}
670

    
671
	}
672

    
673
	public void buildDescriptiveConcepts(ElementImpl dataset)
674
			throws ParseException {
675

    
676
		if (cdmSource.getFeatureData() != null) {
677
			ElementImpl elFeatures = new ElementImpl(document,
678
					DESCRIPTIVE_CONCEPTS);
679
			int f = cdmSource.getTerms().size();
680
			for (int i = 0; i < f; i++) {
681
				DefinedTermBase dtb = cdmSource.getTerms().get(i);
682
				if (dtb instanceof Feature) {
683
					ElementImpl elFeat = new ElementImpl(document,
684
							DESCRIPTIVE_CONCEPT);
685
					Feature feature = (Feature) dtb;
686
					if (feature.getMarkers() != null) {
687
						Set<Marker> markers = feature.getMarkers();
688
						for (Iterator<Marker> m = markers.iterator(); m
689
								.hasNext();) {
690
							Marker marker = m.next();
691
							if (marker.getMarkerType().getLabel()
692
									.equals("DescriptiveConcept")) {
693
								descriptiveConceptCount = buildReference(dtb,
694
										descriptiveConcepts, ID, elFeat, "dc",
695
										descriptiveConceptCount);
696
								buildRepresentation(elFeat, feature);
697
								if (!feature
698
										.getRecommendedModifierEnumeration()
699
										.isEmpty()) {
700
									ElementImpl elModifiers = new ElementImpl(
701
											document, "Modifiers");
702
									for (Iterator<TermVocabulary<DefinedTerm>> menum = feature
703
											.getRecommendedModifierEnumeration()
704
											.iterator(); menum.hasNext();) {
705
										TermVocabulary<DefinedTerm> termVoc = menum.next();
706
										Set<DefinedTerm> sm = termVoc.getTerms();
707
										for (Iterator<DefinedTerm> modif = sm.iterator(); modif.hasNext();) {
708
											DefinedTerm modifier = modif.next();
709
											ElementImpl elModifier = new ElementImpl(
710
													document, "Modifier");
711
											modifiersCount = buildReference(
712
													modifier, modifiers, ID,
713
													elModifier, "mod",
714
													modifiersCount);
715
											buildRepresentation(elModifier,
716
													modifier);
717
											elModifiers.appendChild(elModifier);
718
										}
719
									}
720
									elFeat.appendChild(elModifiers);
721
								}
722
								elFeatures.appendChild(elFeat);
723
							}
724
						}
725
					}
726
				}
727
			}
728
			dataset.appendChild(elFeatures);
729
		}
730
	}
731

    
732
	/**
733
	 * Builds Characters associated with the Dataset
734
	 */
735
	public void buildCharacters(ElementImpl dataset) throws ParseException {
736

    
737
		if (cdmSource.getTerms() != null) {
738
			ElementImpl elCharacters = new ElementImpl(document, CHARACTERS);
739

    
740
			int f = cdmSource.getTerms().size();
741
			for (int i = 0; i < f; i++) {
742
				if (cdmSource.getTerms().get(i) instanceof Feature) {
743
					Feature character = (Feature) cdmSource.getTerms().get(i);
744
					if (character.isSupportsQuantitativeData()) {
745
						ElementImpl elQuantitativeCharacter = new ElementImpl(
746
								document, QUANTITATIVE_CHARACTER);
747
						charactersCount = buildReference(character, characters,
748
								ID, elQuantitativeCharacter, "c",
749
								charactersCount);
750
						buildRepresentation(elQuantitativeCharacter, character);
751
						elCharacters.appendChild(elQuantitativeCharacter);
752
					}
753

    
754
					if (character.isSupportsCategoricalData()) {
755
						ElementImpl elCategoricalCharacter = new ElementImpl(
756
								document, CATEGORICAL_CHARACTER);
757
						charactersCount = buildReference(character, characters,
758
								ID, elCategoricalCharacter, "c",
759
								charactersCount);
760
						buildRepresentation(elCategoricalCharacter, character);
761

    
762
						Set<TermVocabulary<State>> enumerations = character
763
								.getSupportedCategoricalEnumerations();
764
						if (enumerations != null) {
765
							if (enumerations.size() > 0) {
766
								ElementImpl elStates = new ElementImpl(
767
										document, STATES);
768
								TermVocabulary tv = (TermVocabulary) enumerations
769
										.toArray()[0];
770
								Set<State> stateList = tv.getTerms();
771
								for (int j = 0; j < stateList.size(); j++) {
772
									ElementImpl elStateDefinition = new ElementImpl(
773
											document, STATE_DEFINITION);
774
									State state = (State) stateList.toArray()[j];
775
									statesCount = buildReference(state, states,
776
											ID, elStateDefinition, "s",
777
											statesCount);
778
									buildRepresentation(elStateDefinition,
779
											state);
780
									elStates.appendChild(elStateDefinition);
781
								}
782
								elCategoricalCharacter.appendChild(elStates);
783
								elCharacters
784
										.appendChild(elCategoricalCharacter);
785
							}
786
						}
787
					}
788
					if (character.isSupportsTextData()) {
789
						ElementImpl elTextCharacter = new ElementImpl(document,
790
								TEXT_CHARACTER);
791
						textcharactersCount = buildReference(character,
792
								characters, ID, elTextCharacter, TEXT,
793
								textcharactersCount);
794
						buildRepresentation(elTextCharacter, character);
795
						elCharacters.appendChild(elTextCharacter);
796
					}
797
				}
798
			}
799

    
800
			dataset.appendChild(elCharacters);
801
		}
802

    
803
	}
804

    
805
	public void buildCodedDescriptions(ElementImpl dataset)
806
			throws ParseException {
807

    
808
		if (cdmSource.getTaxa() != null) {
809
			ElementImpl elCodedDescriptions = new ElementImpl(document,
810
					CODED_DESCRIPTIONS);
811

    
812
			for (Iterator<? extends TaxonBase> tb = cdmSource.getTaxa()
813
					.iterator(); tb.hasNext();) {
814
				Taxon taxon = (Taxon) tb.next();
815
				Set<TaxonDescription> descriptions = taxon.getDescriptions();
816
				for (Iterator<TaxonDescription> td = descriptions.iterator(); td
817
						.hasNext();) {
818
					TaxonDescription taxonDescription = td.next();
819
					ElementImpl elCodedDescription = new ElementImpl(document,
820
							CODED_DESCRIPTION);
821
					codedDescriptionsCount = buildReference(taxonDescription,
822
							codedDescriptions, ID, elCodedDescription, "D",
823
							codedDescriptionsCount);
824
					buildRepresentation(elCodedDescription, taxonDescription);
825
					buildScope(elCodedDescription, taxonDescription);
826
					buildSummaryData(elCodedDescription, taxonDescription);
827
					elCodedDescriptions.appendChild(elCodedDescription);
828
				}
829
			}
830

    
831
			dataset.appendChild(elCodedDescriptions);
832
		}
833

    
834
	}
835

    
836
	/**
837
	 * Builds Scope associated with a CodedDescription
838
	 */
839
	public void buildScope(ElementImpl element,
840
			TaxonDescription taxonDescription) throws ParseException {
841

    
842
		// <Scope>
843
		// <TaxonName ref="t1"/>
844
		// <Citation ref="p1" location="p. 30"/>
845
		// </Scope>
846

    
847
		ElementImpl scope = new ElementImpl(document, SCOPE);
848

    
849
		Taxon taxon = taxonDescription.getTaxon();
850
		if (taxon != null) {
851
			TaxonName taxonName = taxon.getName();
852
			if (taxonName != null) {
853
				String ref = taxonNames.get(taxonName);
854
				if (!ref.equals("")) {
855
					ElementImpl taxonNameEl = new ElementImpl(document,
856
							TAXON_NAME);
857
					taxonNameEl.setAttribute(REF, ref);
858
					scope.appendChild(taxonNameEl);
859
				}
860
			}
861
		}
862

    
863
		Set<Reference> descriptionSources = new HashSet<Reference>();
864
		for (IdentifiableSource source : taxonDescription.getSources()){
865
			descriptionSources.add(source.getCitation());
866
		}
867
		for (Iterator<Reference> rb = descriptionSources.iterator(); rb.hasNext();) {
868
			Reference descriptionSource = rb.next();
869
			if (descriptionSource.getType().equals(ReferenceType.Article)) {
870

    
871
				ElementImpl citation = new ElementImpl(document, CITATION);
872
				articlesCount = buildReference(descriptionSource, articles,
873
						REF, citation, "p", articlesCount);
874

    
875
				Set<Annotation> annotations = descriptionSource.getAnnotations();
876
				for (Iterator<Annotation> a = annotations.iterator(); a.hasNext();) {
877
					Annotation annotation = a.next();
878
					AnnotationType annotationType = annotation.getAnnotationType();
879
					if (annotationType != null) {
880
						String type = annotationType.getLabel();
881
						if (type.equals("location")) {
882
							citation.setAttribute("location",annotation.getText());
883
						}
884
					}
885
				}
886

    
887
				scope.appendChild(citation);
888
			}
889
		}
890

    
891
		element.appendChild(scope);
892
	}
893

    
894
	/**
895
	 * Builds SummaryData associated with a CodedDescription
896
	 */
897
	public void buildSummaryData(ElementImpl element,
898
			TaxonDescription taxonDescription) throws ParseException {
899

    
900
		// <SummaryData>
901
		// <Categorical ref="c4">
902
		// <State ref="s3"/>
903
		// <State ref="s4"/>
904
		// </Categorical>
905

    
906
		ElementImpl summaryData = new ElementImpl(document, SUMMARY_DATA);
907
		Set<DescriptionElementBase> elements = taxonDescription.getElements();
908
		for (Iterator<DescriptionElementBase> deb = elements.iterator(); deb
909
				.hasNext();) {
910
			DescriptionElementBase descriptionElement = deb.next();
911
			if (descriptionElement instanceof CategoricalData) {
912
				CategoricalData categoricalData = (CategoricalData) descriptionElement;
913
				buildCategorical(summaryData, categoricalData);
914
			}
915
			if (descriptionElement instanceof QuantitativeData) {
916
				QuantitativeData quantitativeData = (QuantitativeData) descriptionElement;
917
				buildQuantitative(summaryData, quantitativeData);
918
			}
919
			if (descriptionElement instanceof TextData) {
920
				TextData textData = (TextData) descriptionElement;
921
				buildTextChar(summaryData, textData);
922
			}
923
		}
924
		element.appendChild(summaryData);
925
	}
926

    
927
	/**
928
	 * Builds Categorical associated with a SummaryData
929
	 */
930
	public void buildCategorical(ElementImpl element,
931
			CategoricalData categoricalData) throws ParseException {
932

    
933
		// <SummaryData>
934
		// <Categorical ref="c4">
935
		// <State ref="s3"/>
936
		// <State ref="s4"/>
937
		// </Categorical>
938

    
939
		ElementImpl categorical = new ElementImpl(document, CATEGORICAL);
940
		Feature feature = categoricalData.getFeature();
941
		buildReference(feature, characters, REF, categorical, "c",
942
				charactersCount);
943
		List<StateData> states = categoricalData.getStateData();
944
		for (Iterator<StateData> sd = states.iterator(); sd.hasNext();) {
945
			StateData stateData = sd.next();
946
			State s = stateData.getState();
947
			buildState(categorical, s);
948
		}
949
		element.appendChild(categorical);
950
	}
951

    
952
	/**
953
	 * Builds State associated with a Categorical
954
	 */
955
	public void buildState(ElementImpl element, State s) throws ParseException {
956

    
957
		// <SummaryData>
958
		// <Categorical ref="c4">
959
		// <State ref="s3"/>
960
		// <State ref="s4"/>
961
		// </Categorical>
962

    
963
		ElementImpl state = new ElementImpl(document, STATE);
964
		buildReference(s, states, REF, state, "s", statesCount);
965
		element.appendChild(state);
966
	}
967

    
968
	/**
969
	 * Builds Quantitative associated with a SummaryData
970
	 */
971
	public void buildQuantitative(ElementImpl element,
972
			QuantitativeData quantitativeData) throws ParseException {
973

    
974
		// <Quantitative ref="c2">
975
		// <Measure type="Min" value="2.3"></Measure>
976
		// <Measure type="Mean" value="5.1"/>
977
		// <Measure type="Max" value="7.9"/>
978
		// <Measure type="SD" value="1.3"/>
979
		// <Measure type="N" value="20"/>
980
		// </Quantitative>
981

    
982
		ElementImpl quantitative = new ElementImpl(document, QUANTITATIVE);
983
		Feature feature = quantitativeData.getFeature();
984
		buildReference(feature, characters, REF, quantitative, "c",
985
				charactersCount);
986
		Set<StatisticalMeasurementValue> statisticalValues = quantitativeData
987
				.getStatisticalValues();
988
		for (Iterator<StatisticalMeasurementValue> smv = statisticalValues
989
				.iterator(); smv.hasNext();) {
990
			StatisticalMeasurementValue statisticalValue = smv.next();
991
			buildMeasure(quantitative, statisticalValue);
992
		}
993
		element.appendChild(quantitative);
994
	}
995

    
996
	/**
997
	 * Builds Measure associated with a Quantitative
998
	 */
999
	public void buildMeasure(ElementImpl element,
1000
			StatisticalMeasurementValue statisticalValue) throws ParseException {
1001

    
1002
		// <Quantitative ref="c2">
1003
		// <Measure type="Min" value="2.3"></Measure>
1004
		// <Measure type="Mean" value="5.1"/>
1005
		// <Measure type="Max" value="7.9"/>
1006
		// <Measure type="SD" value="1.3"/>
1007
		// <Measure type="N" value="20"/>
1008
		// </Quantitative>
1009

    
1010
		ElementImpl measure = new ElementImpl(document, MEASURE);
1011
		StatisticalMeasure type = statisticalValue.getType();
1012
		String label = type.getLabel();
1013
		if (label.equals("Average")) {
1014
			measure.setAttribute("type", "Mean");
1015
		} else if (label.equals("StandardDeviation")) {
1016
			measure.setAttribute("type", "SD");
1017
		} else if (label.equals("SampleSize")) {
1018
			measure.setAttribute("type", "N");
1019
		} else {
1020
			measure.setAttribute("type", label);
1021
		}
1022
		float value = statisticalValue.getValue();
1023
		measure.setAttribute("value", String.valueOf(value));
1024
		element.appendChild(measure);
1025
	}
1026

    
1027
	/**
1028
	 * Builds TextChar associated with a SummaryData
1029
	 */
1030
	public void buildTextChar(ElementImpl element, TextData textData)
1031
			throws ParseException {
1032

    
1033
		// <TextChar ref="c3">
1034
		// <Content>Free form text</Content>
1035
		// </TextChar>
1036

    
1037
		ElementImpl textChar = new ElementImpl(document, TEXT_CHAR);
1038
		Feature feature = textData.getFeature();
1039
		buildReference(feature, characters, REF, textChar, "c", charactersCount);
1040
		Map<Language, LanguageString> multilanguageText = textData
1041
				.getMultilanguageText();
1042
		for (Language language : multilanguageText.keySet()) {
1043
			LanguageString languageString = multilanguageText.get(language);
1044
			buildContent(textChar, languageString);
1045
		}
1046
		element.appendChild(textChar);
1047
	}
1048

    
1049
	/**
1050
	 * Builds Content associated with a TextChar
1051
	 */
1052
	public void buildContent(ElementImpl element, LanguageString languageString)
1053
			throws ParseException {
1054

    
1055
		// <TextChar ref="c3">
1056
		// <Content>Free form text</Content>
1057
		// </TextChar>
1058

    
1059
		ElementImpl content = new ElementImpl(document, CONTENT);
1060
		Language language = languageString.getLanguage();
1061
		String text = languageString.getText();
1062
		if (!language.getIso639_1().equals(defaultLanguage.getIso639_1())) {
1063
			content.setAttribute("xml:lang", language.getIso639_1());
1064
		}
1065
		content.setTextContent(text);
1066
		element.appendChild(content);
1067
	}
1068

    
1069
	/**
1070
	 * Builds an element Agent referring to Agent defined later in the SDD file
1071
	 */
1072
	public void buildRefAgent(ElementImpl element, TeamOrPersonBase ag,
1073
			String role) throws ParseException {
1074
		if (ag instanceof Person) {
1075
			Person p = (Person) ag;
1076
			ElementImpl agent = new ElementImpl(document, AGENT);
1077
			if (ag.getMarkers() != null) {
1078
				Set<Marker> markers = ag.getMarkers();
1079
				for (Iterator<Marker> m = markers.iterator(); m.hasNext();) {
1080
					Marker marker = m.next();
1081
					if (marker.getMarkerType().getLabel().equals("editor")) {
1082
						agent.setAttribute(ROLE, "edt");
1083
					}
1084
				}
1085
			} else {
1086
				agent.setAttribute(ROLE, role);
1087
			}
1088
			agentsCount = buildReference(p, agents, REF, agent, "a",
1089
					agentsCount);
1090
			element.appendChild(agent);
1091
		}
1092

    
1093
		if (ag instanceof Team) {
1094
			Team team = (Team) ag;
1095
			for (int i = 0; i < team.getTeamMembers().size(); i++) {
1096
				Person author = team.getTeamMembers().get(i);
1097
				ElementImpl agent = new ElementImpl(document, AGENT);
1098
				if (author.getMarkers() != null) {
1099
					Set<Marker> markers = author.getMarkers();
1100
					if (!markers.isEmpty()) {
1101
						for (Iterator<Marker> m = markers.iterator(); m
1102
								.hasNext();) {
1103
							Marker marker = m.next();
1104
							if (marker.getMarkerType().getLabel()
1105
									.equals("editor")) {
1106
								agent.setAttribute(ROLE, "edt");
1107
							}
1108
						}
1109
					} else {
1110
						agent.setAttribute(ROLE, role);
1111
					}
1112
				} else {
1113
					agent.setAttribute(ROLE, role);
1114
				}
1115
				if (author.getSources() != null) {
1116
					IdentifiableSource os = (IdentifiableSource) author
1117
							.getSources().toArray()[0];
1118
					String id = os.getIdInSource();
1119
					if (id != null) {
1120
						if (!id.equals("")) {
1121
							if (!agents.containsValue(id)) {
1122
								agent.setAttribute(REF, id);
1123
							} else if (!agents.containsValue("a"
1124
									+ (agentsCount + 1))) {
1125
								agent.setAttribute(REF, "a" + (agentsCount + 1));
1126
								agentsCount++;
1127
							} else {
1128
								agent.setAttribute(REF, id + (agentsCount + 1));
1129
								agentsCount++;
1130
							}
1131
						} else {
1132
							agent.setAttribute(REF, "a" + (agentsCount + 1));
1133
							agentsCount++;
1134
						}
1135
					} else {
1136
						agent.setAttribute(REF, "a" + (agentsCount + 1));
1137
						agentsCount++;
1138
					}
1139
				} else {
1140
					agent.setAttribute(REF, "a" + (agentsCount + 1));
1141
					agentsCount++;
1142
				}
1143
				agents.put(author, agent.getAttribute(REF));
1144
				element.appendChild(agent);
1145
			}
1146
		}
1147
	}
1148

    
1149
	/**
1150
	 * Builds Agents associated with the Dataset
1151
	 */
1152
	public void buildAgents(ElementImpl dataset) throws ParseException {
1153

    
1154
		if (cdmSource.getAgents() != null) {
1155
			ElementImpl elAgents = new ElementImpl(document, AGENTS);
1156

    
1157
			for (int i = 0; i < cdmSource.getAgents().size(); i++) {
1158
				ElementImpl elAgent = new ElementImpl(document, AGENT);
1159
				AgentBase personagent = cdmSource.getAgents().get(i);
1160
				if (personagent instanceof Person) {
1161
					if (personagent.getMarkers() != null) {
1162
						Set<Marker> markers = personagent.getMarkers();
1163
						for (Iterator<Marker> m = markers.iterator(); m
1164
								.hasNext();) {
1165
							Marker marker = m.next();
1166
							if (marker.getMarkerType().getLabel()
1167
									.equals("editor")) {
1168
								agentsCount = buildReference(personagent,
1169
										agents, ID, elAgent, "a", agentsCount);
1170
							}
1171
						}
1172
					}
1173
					agentsCount = buildReference(personagent, agents, ID,
1174
							elAgent, "a", agentsCount);
1175
					buildRepresentation(elAgent, personagent);
1176
					elAgents.appendChild(elAgent);
1177
				}
1178
			}
1179

    
1180
			dataset.appendChild(elAgents);
1181
		}
1182
	}
1183

    
1184
	public void buildCharacterTrees(ElementImpl dataset) throws ParseException {
1185

    
1186
		if (cdmSource.getFeatureData() != null) {
1187
			ElementImpl elChartrees = new ElementImpl(document, CHARACTER_TREES);
1188

    
1189
			for (int i = 0; i < cdmSource.getFeatureData().size(); i++) {
1190
				VersionableEntity featu = cdmSource.getFeatureData().get(i);
1191
				if (featu instanceof FeatureTree) {
1192
					FeatureTree ft = (FeatureTree) featu;
1193
					ElementImpl elChartree = new ElementImpl(document,
1194
							CHARACTER_TREE);
1195
					chartreeCount = buildReference(featu, featuretrees, ID,
1196
							elChartree, "ct", chartreeCount);
1197
					buildRepresentation(elChartree, ft);
1198
					elChartrees.appendChild(elChartree);
1199
					ElementImpl elNodes = new ElementImpl(document, NODES);
1200
					elChartree.appendChild(elNodes);
1201
					List<FeatureNode> roots = ft.getRootChildren();
1202
					for (Iterator<FeatureNode> fn = roots.iterator(); fn
1203
							.hasNext();) {
1204
						FeatureNode featureNode = fn.next();
1205
						buildBranches(featureNode, elNodes, true);
1206
					}
1207
				}
1208
			}
1209
			dataset.appendChild(elChartrees);
1210
		}
1211
	}
1212

    
1213
	public void buildClassifications(ElementImpl dataset) throws ParseException {
1214

    
1215
		if (cdmSource.getTaxa() != null) {
1216
			ElementImpl elTaxonHierarchies = new ElementImpl(document,
1217
					"TaxonHierarchies");
1218
			ElementImpl elTaxonHierarchy = new ElementImpl(document,
1219
					"TaxonHierarchy");
1220
			for (Iterator<? extends TaxonBase> tb = cdmSource.getTaxa()
1221
					.iterator(); tb.hasNext();) {
1222
				Taxon taxon = (Taxon) tb.next();
1223
				if (taxon.getTaxonNodes() != null) {
1224
					for (Iterator<TaxonNode> tn = taxon.getTaxonNodes()
1225
							.iterator(); tn.hasNext();) {
1226
						TaxonNode taxonnode = tn.next();
1227
						if (taxonnode.isTopmostNode()) {
1228
							ElementImpl elNode = new ElementImpl(document, "Node");
1229
							taxonNodesCount = buildReference(taxonnode,
1230
									taxonNodes, ID, elNode, "tn", taxonNodesCount);
1231
							ElementImpl elTaxonName = new ElementImpl(document, TAXON_NAME);
1232
							taxonNamesCount = buildReference(taxonnode.getTaxon().getName(),
1233
									taxonNames, REF, elTaxonName, "t", taxonNamesCount);
1234
							elNode.appendChild(elTaxonName);
1235
							elTaxonHierarchy.appendChild(elNode);
1236
							if (taxonnode.hasChildNodes()) {buildTaxonBranches(
1237
									taxonnode.getChildNodes(), taxonnode, elTaxonHierarchy);
1238
							}
1239
						}
1240
					}
1241
				}
1242
			}
1243
			elTaxonHierarchies.appendChild(elTaxonHierarchy);
1244
			dataset.appendChild(elTaxonHierarchies);
1245
		}
1246
	}
1247

    
1248
	private void buildTaxonBranches(List<TaxonNode> children, TaxonNode parent,
1249
			ElementImpl elTaxonHierarchy) {
1250
		if (children != null) {
1251
			for (Iterator<TaxonNode> tn = children.iterator(); tn.hasNext();) {
1252
				TaxonNode taxonnode = tn.next();
1253
				ElementImpl elNode = new ElementImpl(document, "Node");
1254
				ElementImpl elParent = new ElementImpl(document, PARENT);
1255
				ElementImpl elTaxonName = new ElementImpl(document, TAXON_NAME);
1256
				if (taxonnode.hasChildNodes()) {
1257
					buildTaxonBranches(taxonnode.getChildNodes(), taxonnode,
1258
							elTaxonHierarchy);
1259
				}
1260
				taxonNodesCount = buildReference(taxonnode, taxonNodes, ID,
1261
						elNode, "tn", taxonNodesCount);
1262
				taxonNodesCount = buildReference(parent, taxonNodes, REF,
1263
						elParent, "tn", taxonNodesCount);
1264
				taxonNamesCount = buildReference(
1265
						taxonnode.getTaxon().getName(), taxonNames, REF,
1266
						elTaxonName, "t", taxonNamesCount);
1267
				elNode.appendChild(elParent);
1268
				elNode.appendChild(elTaxonName);
1269
				elTaxonHierarchy.appendChild(elNode);
1270
			}
1271
		}
1272
	}
1273

    
1274
	public void buildBranches(FeatureNode parent, ElementImpl element,
1275
			boolean isRoot) {
1276
		List<FeatureNode> children = parent.getChildNodes();
1277
		if (!parent.isLeaf()) {
1278
			ElementImpl elCharNode = new ElementImpl(document, NODE);
1279
			charnodeCount = buildReference(parent, featuretrees, ID,
1280
					elCharNode, "cn", charnodeCount);
1281
			FeatureNode grandparent = parent.getParent();
1282
			if ((grandparent != null) && (!isRoot)) {
1283
				ElementImpl elParent = new ElementImpl(document, PARENT);
1284
				charnodeCount = buildReference(grandparent, featuretrees, REF,
1285
						elParent, "cn", charnodeCount);
1286
				elCharNode.appendChild(elParent);
1287
			}
1288
			ElementImpl elDescriptiveConcept = new ElementImpl(document,
1289
					DESCRIPTIVE_CONCEPT);
1290
			Feature fref = parent.getFeature();
1291
			descriptiveConceptCount = buildReference(fref, descriptiveConcepts,
1292
					REF, elDescriptiveConcept, "dc", descriptiveConceptCount);
1293
			elCharNode.appendChild(elDescriptiveConcept);
1294
			element.appendChild(elCharNode);
1295
			for (Iterator<FeatureNode> ifn = children.iterator(); ifn.hasNext();) {
1296
				FeatureNode fn = ifn.next();
1297
				buildBranches(fn, element, false);
1298
			}
1299
		} else {
1300
			ElementImpl elCharNode = new ElementImpl(document, CHAR_NODE);
1301
			ElementImpl elParent = new ElementImpl(document, PARENT);
1302
			FeatureNode grandparent = parent.getParent();
1303
			charnodeCount = buildReference(grandparent, featuretrees, REF,
1304
					elParent, "cn", charnodeCount);
1305
			charnodeCount = buildReference(parent, featuretrees, ID,
1306
					elCharNode, "cn", charnodeCount);
1307
			ElementImpl elCharacter = new ElementImpl(document, CHARACTER);
1308
			Feature fref = parent.getFeature();
1309
			boolean dependencies = false;
1310
			ElementImpl elDependecyRules = new ElementImpl(document,
1311
					"DependecyRules");
1312
			if (parent.getInapplicableIf() != null) {
1313
				Set<State> innaplicableIf = parent.getInapplicableIf();
1314
				ElementImpl elInnaplicableIf = new ElementImpl(document,
1315
						"InapplicableIf");
1316
				for (State state : innaplicableIf) {
1317
					ElementImpl elState = new ElementImpl(document, STATE);
1318
					buildReference(state, states, REF, elState, "State",
1319
							statesCount);
1320
					elInnaplicableIf.appendChild(elState);
1321
				}
1322
				elDependecyRules.appendChild(elInnaplicableIf);
1323
				dependencies = true;
1324
			}
1325
			if (parent.getOnlyApplicableIf() != null) {
1326
				Set<State> onlyApplicableIf = parent.getOnlyApplicableIf();
1327
				ElementImpl elOnlyApplicableIf = new ElementImpl(document,
1328
						"OnlyApplicableIf");
1329
				for (State state : onlyApplicableIf) {
1330
					ElementImpl elState = new ElementImpl(document, STATE);
1331
					buildReference(state, states, REF, elState, "State",
1332
							statesCount);
1333
					elOnlyApplicableIf.appendChild(elState);
1334
				}
1335
				elDependecyRules.appendChild(elOnlyApplicableIf);
1336
				dependencies = true;
1337
			}
1338
			if (dependencies == true) {
1339
                elCharNode.appendChild(elDependecyRules);
1340
            }
1341
			charactersCount = buildReference(fref, characters, REF,
1342
					elCharacter, "c", charactersCount);
1343
			elCharNode.appendChild(elCharacter);
1344
			elCharNode.appendChild(elParent);
1345
			element.appendChild(elCharNode);
1346
		}
1347
	}
1348

    
1349
	public void buildMediaObjects(ElementImpl dataset) throws ParseException {
1350

    
1351
		if (cdmSource.getMedia() != null) {
1352
			ElementImpl elMediaObjects = new ElementImpl(document,
1353
					MEDIA_OBJECTS);
1354

    
1355
			for (int i = 0; i < cdmSource.getMedia().size(); i++) {
1356
				ElementImpl elMediaObject = new ElementImpl(document,
1357
						MEDIA_OBJECT);
1358
				Media mediobj = (Media) cdmSource.getMedia().get(i);
1359
				mediasCount = buildReference(mediobj, medias, ID,
1360
						elMediaObject, "t", mediasCount);
1361
				buildRepresentation(elMediaObject, mediobj);
1362
				Set<MediaRepresentation> smr = mediobj.getRepresentations();
1363
				for (Iterator<MediaRepresentation> mr = smr.iterator(); mr
1364
						.hasNext();) {
1365
					MediaRepresentation mediarep = mr.next();
1366
					ElementImpl elType = new ElementImpl(document, "Type");
1367
					elType.appendChild(document.createTextNode(mediarep
1368
							.getMimeType()));
1369
					elMediaObject.appendChild(elType);
1370
					List<MediaRepresentationPart> lmrp = mediarep.getParts();
1371
					for (Iterator<MediaRepresentationPart> mrp = lmrp
1372
							.iterator(); mrp.hasNext();) {
1373
						MediaRepresentationPart mediareppart = mrp.next();
1374
						ElementImpl elSource = new ElementImpl(document,
1375
								"Source");
1376
						elSource.setAttribute("href", mediareppart.getUri()
1377
								.toString());
1378
						elMediaObject.appendChild(elSource);
1379
					}
1380
				}
1381
				elMediaObjects.appendChild(elMediaObject);
1382
			}
1383
			dataset.appendChild(elMediaObjects);
1384
		}
1385
	}
1386

    
1387
	public void buildPublications(ElementImpl dataset) throws ParseException {
1388

    
1389
		if (cdmSource.getReferences() != null) {
1390
			ElementImpl elPublications = new ElementImpl(document, PUBLICATIONS);
1391
			boolean editorial = false;
1392
			for (int i = 0; i < cdmSource.getReferences().size(); i++) {
1393
				ElementImpl elPublication = new ElementImpl(document,
1394
						"Publication");
1395
				Reference publication = cdmSource.getReferences().get(i);
1396
				Set<Annotation> annotations = publication.getAnnotations();
1397
				for (Iterator<Annotation> a = annotations.iterator(); a
1398
						.hasNext();) {
1399
					Annotation annotation = a.next();
1400
					AnnotationType annotationType = annotation
1401
							.getAnnotationType();
1402
					if (annotationType != null && annotationType.equals(AnnotationType.EDITORIAL())) {
1403
						editorial = true;
1404
					} else {
1405
						editorial = false;
1406
					}
1407
				}
1408
				if (!editorial) {
1409
					articlesCount = buildReference(publication, articles, ID,
1410
							elPublication, "p", articlesCount);
1411
					buildRepresentation(elPublication, (IDatabase) publication);
1412
					elPublications.appendChild(elPublication);
1413
				}
1414
			}
1415
			dataset.appendChild(elPublications);
1416
		}
1417
	}
1418

    
1419
	public int buildReference(VersionableEntity ve, Map references,
1420
			String refOrId, ElementImpl element, String prefix, int count)
1421
			throws ParseException {
1422
		if (references.containsKey(ve)) {
1423
			element.setAttribute(refOrId, (String) references.get(ve));
1424
		} else {
1425
			if (ve instanceof IdentifiableEntity) {
1426
				IdentifiableEntity ie = (IdentifiableEntity) ve;
1427
				if (ie.getSources().size() > 0) {
1428
					IdentifiableSource os = (IdentifiableSource) ie
1429
							.getSources().toArray()[0];
1430
					String id = os.getIdInSource();
1431
					String uri = os.getCitationMicroReference();
1432
					if (uri != null) {
1433
						element.setAttribute(URI, uri);
1434
					}
1435
					if (id != null) {
1436
						if (!id.equals("")) {
1437
							if (!references.containsValue(id)) {
1438
								element.setAttribute(refOrId, id);
1439
							} else {
1440
                                while (element.getAttribute(refOrId).equals("")) {
1441
									if (!references.containsValue(prefix
1442
											+ (count + 1))) {
1443
										element.setAttribute(refOrId, prefix
1444
												+ (count + 1));
1445
									}
1446
									count++;
1447
								}
1448
                            }
1449
						} else {
1450
                            while (element.getAttribute(refOrId).equals("")) {
1451
								if (!references.containsValue(prefix
1452
										+ (count + 1))) {
1453
									element.setAttribute(refOrId, prefix
1454
											+ (count + 1));
1455
								}
1456
								count++;
1457
							}
1458
                        }
1459
					} else {
1460
                        while (element.getAttribute(refOrId).equals("")) {
1461
							if (!references.containsValue(prefix + (count + 1))) {
1462
								element.setAttribute(refOrId, prefix
1463
										+ (count + 1));
1464
							}
1465
							count++;
1466
						}
1467
                    }
1468
				} else {
1469
                    while (element.getAttribute(refOrId).equals("")) {
1470
						if (!references.containsValue(prefix + (count + 1))) {
1471
							element.setAttribute(refOrId, prefix + (count + 1));
1472
						}
1473
						count++;
1474
					}
1475
                }
1476
			} else {
1477
                while (element.getAttribute(refOrId).equals("")) {
1478
					if (!references.containsValue(prefix + (count + 1))) {
1479
						element.setAttribute(refOrId, prefix + (count + 1));
1480
					}
1481
					count++;
1482
				}
1483
            }
1484
			references.put(ve, element.getAttribute(refOrId));
1485
		}
1486
		return count;
1487
	}
1488

    
1489
	public void buildGeographicAreas(ElementImpl dataset) {
1490
		if (cdmSource.getTerms() != null) {
1491
			ElementImpl elGeographicAreas = new ElementImpl(document,
1492
					"GeographicAreas");
1493

    
1494
			int f = cdmSource.getTerms().size();
1495
			for (int i = 0; i < f; i++) {
1496
				if (cdmSource.getTerms().get(i) instanceof NamedArea) {
1497
					NamedArea na = (NamedArea) cdmSource.getTerms().get(i);
1498
					for (Iterator<Marker> mark = na.getMarkers().iterator(); mark
1499
							.hasNext();) {
1500
						Marker marker = mark.next();
1501
						if (marker.getMarkerType().getLabel()
1502
								.equals("SDDGeographicArea")) {
1503
							ElementImpl elGeographicArea = new ElementImpl(
1504
									document, "GeographicArea");
1505
							namedAreasCount = buildReference(na, namedAreas,
1506
									ID, elGeographicArea, "a", namedAreasCount);
1507
							buildRepresentation(elGeographicArea, na);
1508
							elGeographicAreas.appendChild(elGeographicArea);
1509
						}
1510
					}
1511

    
1512
				}
1513
			}
1514
			dataset.appendChild(elGeographicAreas);
1515
		}
1516
	}
1517

    
1518
	public void buildSpecimens(ElementImpl dataset) throws ParseException {
1519

    
1520
		if (cdmSource.getOccurrences() != null) {
1521
			ElementImpl elSpecimens = new ElementImpl(document, "Specimens");
1522

    
1523
			for (int i = 0; i < cdmSource.getOccurrences().size(); i++) {
1524
				ElementImpl elSpecimen = new ElementImpl(document, "Specimen");
1525
				SpecimenOrObservationBase<?> sob = cdmSource.getOccurrences().get(i);
1526
				if (sob.getRecordBasis().isPreservedSpecimen()) {
1527
					specimenCount = buildReference(sob, specimens, ID, elSpecimen, "s", specimenCount);
1528
					buildRepresentation(elSpecimen, sob);
1529
					elSpecimens.appendChild(elSpecimen);
1530
				}
1531
			}
1532
			dataset.appendChild(elSpecimens);
1533
		}
1534

    
1535
	}
1536

    
1537
}
(3-3/5)