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
package eu.etaxonomy.cdm.io.sdd.out;
10

    
11
import java.io.File;
12
import java.io.FileOutputStream;
13
import java.io.IOException;
14
import java.io.OutputStream;
15
import java.io.OutputStreamWriter;
16
import java.io.Writer;
17
import java.math.BigDecimal;
18
import java.util.HashMap;
19
import java.util.HashSet;
20
import java.util.Iterator;
21
import java.util.List;
22
import java.util.Map;
23
import java.util.Set;
24

    
25
import javax.xml.bind.Marshaller;
26

    
27
import org.apache.logging.log4j.LogManager;
28
import org.apache.logging.log4j.Logger;
29
import org.apache.xerces.dom.DocumentImpl;
30
import org.apache.xerces.dom.ElementImpl;
31
import org.apache.xerces.impl.xpath.regex.ParseException;
32
import org.apache.xml.serialize.DOMSerializer;
33
import org.apache.xml.serialize.OutputFormat;
34
import org.apache.xml.serialize.XMLSerializer;
35
import org.joda.time.DateTime;
36
import org.joda.time.format.DateTimeFormatter;
37
import org.joda.time.format.ISODateTimeFormat;
38
import org.springframework.util.ResourceUtils;
39
import org.xml.sax.SAXException;
40

    
41
import eu.etaxonomy.cdm.io.jaxb.CdmMarshallerListener;
42
import eu.etaxonomy.cdm.model.agent.AgentBase;
43
import eu.etaxonomy.cdm.model.agent.Person;
44
import eu.etaxonomy.cdm.model.agent.Team;
45
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
46
import eu.etaxonomy.cdm.model.common.Annotation;
47
import eu.etaxonomy.cdm.model.common.AnnotationType;
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.VersionableEntity;
54
import eu.etaxonomy.cdm.model.description.CategoricalData;
55
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
56
import eu.etaxonomy.cdm.model.description.Feature;
57
import eu.etaxonomy.cdm.model.description.FeatureState;
58
import eu.etaxonomy.cdm.model.description.QuantitativeData;
59
import eu.etaxonomy.cdm.model.description.State;
60
import eu.etaxonomy.cdm.model.description.StateData;
61
import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
62
import eu.etaxonomy.cdm.model.description.StatisticalMeasurementValue;
63
import eu.etaxonomy.cdm.model.description.TaxonDescription;
64
import eu.etaxonomy.cdm.model.description.TextData;
65
import eu.etaxonomy.cdm.model.location.NamedArea;
66
import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
67
import eu.etaxonomy.cdm.model.media.Media;
68
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
69
import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
70
import eu.etaxonomy.cdm.model.media.Rights;
71
import eu.etaxonomy.cdm.model.name.TaxonName;
72
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
73
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
74
import eu.etaxonomy.cdm.model.reference.IDatabase;
75
import eu.etaxonomy.cdm.model.reference.Reference;
76
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
77
import eu.etaxonomy.cdm.model.reference.ReferenceType;
78
import eu.etaxonomy.cdm.model.taxon.Taxon;
79
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
80
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
81
import eu.etaxonomy.cdm.model.term.DefinedTerm;
82
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
83
import eu.etaxonomy.cdm.model.term.Representation;
84
import eu.etaxonomy.cdm.model.term.TermBase;
85
import eu.etaxonomy.cdm.model.term.TermNode;
86
import eu.etaxonomy.cdm.model.term.TermTree;
87
import eu.etaxonomy.cdm.model.term.TermVocabulary;
88

    
89
/**
90
 * Writes the SDD XML file.
91
 *
92
 * @author h.fradin
93
 * @since 10.12.2008
94
 */
95
public class SDDDocumentBuilder {
96

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

    
103
	private final Map<Person, String> agents = new HashMap<>();
104
	private final Map<TaxonName, String> taxonNames = new HashMap<>();
105
	private final Map<Feature, String> characters = 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 int agentsCount = 0;
118
	private int articlesCount = 0;
119
	private int codedDescriptionsCount = 0;
120
	private int taxonNamesCount = 0;
121
	private int charactersCount = 0;
122
	private int textcharactersCount = 0;
123
	private int mediasCount = 0;
124
	private int statesCount = 0;
125
	private final int featureNodesCount = 0;
126
	private int chartreeCount = 0;
127
	private int charnodeCount = 0;
128
	private int taxonNodesCount = 0;
129
	private int namedAreasCount = 0;
130
	private int specimenCount = 0;
131
	private int descriptiveConceptCount = 0;
132
	private int modifiersCount = 0;
133

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

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

    
196
	private static final Logger logger = LogManager.getLogger(SDDDocumentBuilder.class);
197

    
198
	public SDDDocumentBuilder() throws SAXException, IOException {
199
		document = new DocumentImpl();
200
	}
201

    
202
	public void marshal(SDDDataSet cdmSource, File sddDestination)
203
			throws IOException {
204

    
205
		this.cdmSource = cdmSource;
206
		Marshaller marshaller;
207
		CdmMarshallerListener marshallerListener = new CdmMarshallerListener();
208
		logger.info("Start marshalling");
209
		writeCDMtoSDD(sddDestination);
210

    
211
	}
212

    
213
	public void marshal(SDDDataSet cdmSource, String sddDestinationFileName)
214
			throws IOException {
215

    
216
		this.cdmSource = cdmSource;
217
		Marshaller marshaller;
218
		CdmMarshallerListener marshallerListener = new CdmMarshallerListener();
219
		logger.info("Start marshalling");
220
		writeCDMtoSDD(ResourceUtils.getFile(sddDestinationFileName));
221

    
222
	}
223

    
224
    public void marshal(SDDDataSet dataSet, OutputStream stream) throws IOException {
225
        this.cdmSource = dataSet;
226
        logger.info("Start marshalling");
227
        try {
228
            buildDocument();
229
        } catch (ParseException e) {
230
            e.printStackTrace();
231
        }
232

    
233
        OutputFormat format = new OutputFormat(document, "UTF-8", true);
234

    
235
        writer = new OutputStreamWriter(stream, "UTF-8");
236

    
237
        xmlserializer = new XMLSerializer(writer, format);
238
        domi = xmlserializer.asDOMSerializer(); // As a DOM Serializer
239

    
240
        domi.serialize(document.getDocumentElement());
241

    
242
        writer.close();
243
    }
244
	/**
245
	 * Write the DOM document.
246
	 *
247
	 * @param base
248
	 * @throws IOException
249
	 */
250
	public void writeCDMtoSDD(File sddDestination) throws IOException {
251

    
252
		try {
253
			buildDocument();
254
		} catch (ParseException e) {
255
			e.printStackTrace();
256
		}
257

    
258
		OutputFormat format = new OutputFormat(document, "UTF-8", true);
259

    
260
		FileOutputStream fos = new FileOutputStream(sddDestination);
261

    
262
		writer = new OutputStreamWriter(fos, "UTF-8");
263

    
264
		xmlserializer = new XMLSerializer(writer, format);
265
		domi = xmlserializer.asDOMSerializer(); // As a DOM Serializer
266

    
267
		domi.serialize(document.getDocumentElement());
268

    
269
		writer.close();
270
	}
271

    
272
	// #############
273
	// # BUILD DOM #
274
	// #############
275

    
276
	/**
277
	 * Builds the whole document.
278
	 *
279
	 * @param base
280
	 *            the Base
281
	 * @throws ParseException
282
	 */
283
	public void buildDocument() throws ParseException {
284

    
285
		// create <Datasets> = root node
286
		ElementImpl baselement = new ElementImpl(document, DATASETS);
287
		baselement.setAttribute("xmlns:xsi",
288
				"http://www.w3.org/2001/XMLSchema-instance");
289
		baselement.setAttribute("xmlns", "http://rs.tdwg.org/UBIF/2006/");
290
		baselement
291
				.setAttribute("xsi:schemaLocation",
292
						"http://rs.tdwg.org/UBIF/2006 http://rs.tdwg.org/UBIF/2006/Schema/1.1/SDD.xsd");
293

    
294
		buildTechnicalMetadata(baselement);
295

    
296
		List<Reference> references = cdmSource.getReferences();
297
		Iterator<Reference> iterator = references.iterator();
298
		IDatabase d = ReferenceFactory.newDatabase();
299
		while (iterator.hasNext()) {
300
			Reference reference = iterator.next();
301
			if (reference.getType().equals(ReferenceType.Database)) {
302
				buildDataset(baselement, reference);
303
			}
304
		}
305
		document.appendChild(baselement);
306
	}
307

    
308
	// #############
309
	// # BUILD DOM #
310
	// #############
311

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

    
335
		ElementImpl generator = new ElementImpl(document, GENERATOR);
336
		generator.setAttribute("name", "EDIT CDM");
337
		generator.setAttribute("version", "v1");
338
		generator
339
				.setAttribute(
340
						"notes",
341
						"This SDD file has been generated by the SDD export functionality of the EDIT platform for Cybertaxonomy - Copyright (c) 2008");
342
		technicalMetadata.appendChild(generator);
343

    
344
		baselement.appendChild(technicalMetadata);
345
	}
346

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

    
371
	/**
372
	 * Builds a Representation element using a Reference
373
	 */
374
	public void buildRepresentation(ElementImpl element, IDatabase reference)
375
			throws ParseException {
376

    
377
		// create <Representation> element
378
		ElementImpl representation = new ElementImpl(document, REPRESENTATION);
379
		element.appendChild(representation);
380
		buildLabel(representation, reference.getTitleCache());
381

    
382
		Set<Annotation> annotations = ((Reference) reference).getAnnotations();
383
		Iterator<Annotation> iterator = annotations.iterator();
384
		String detailText = null;
385
		if (iterator.hasNext()) {
386
			Annotation annotation = iterator.next();
387
			detailText = annotation.getText();
388
		}
389

    
390
		if (detailText != null && !detailText.equals("")) {
391
			ElementImpl detail = new ElementImpl(document, DETAIL);
392
			detail.appendChild(document.createTextNode(detailText));
393
			representation.appendChild(detail);
394
		}
395

    
396
		Set<Media> rm = ((Reference) reference).getMedia();
397

    
398
		if (rm != null && rm.size() > 0) {
399
			ElementImpl mediaObject;
400

    
401
			for (int i = 0; i < rm.size(); i++) {
402
				mediaObject = new ElementImpl(document, MEDIA_OBJECT);
403
				mediasCount = buildReference((Media) rm.toArray()[i], medias,
404
						REF, mediaObject, "m", mediasCount);
405
				representation.appendChild(mediaObject);
406
			}
407
		}
408

    
409
	}
410

    
411
	/**
412
	 * Builds a Representation element using a Feature
413
	 */
414
	public void buildRepresentation(ElementImpl element, TermBase tb)
415
			throws ParseException {
416

    
417
		// create <Representation> element
418
		ElementImpl representation = new ElementImpl(document, REPRESENTATION);
419
		element.appendChild(representation);
420

    
421
		Set<Representation> representations = tb.getRepresentations();
422
		if (representations != null) {
423
			if (!representations.isEmpty()) {
424
				String label = ((Representation) representations.toArray()[0])
425
						.getLabel();
426
				buildLabel(representation, label);
427
				String detailText = tb.getDescription();
428

    
429
				if (detailText != null && !detailText.equals("")) {
430
					if (!detailText.equals(label)) {
431
						ElementImpl detail = new ElementImpl(document, DETAIL);
432
						detail.appendChild(document.createTextNode(detailText));
433
						representation.appendChild(detail);
434
					}
435
				}
436

    
437
			}
438
		}
439

    
440
		if (tb instanceof DefinedTermBase) {
441
			DefinedTermBase dtb = (DefinedTermBase) tb;
442
			Set<Media> rm = dtb.getMedia();
443

    
444
			if (rm != null && rm.size() > 0) {
445
				ElementImpl mediaObject;
446

    
447
				for (int i = 0; i < rm.size(); i++) {
448
					mediaObject = new ElementImpl(document, MEDIA_OBJECT);
449
					mediasCount = buildReference((Media) rm.toArray()[i],
450
							medias, REF, mediaObject, "m", mediasCount);
451
					representation.appendChild(mediaObject);
452
				}
453
			}
454
		}
455
	}
456

    
457
	/**
458
	 * Builds a Representation element using an IdentifiableEntity
459
	 */
460
	public void buildRepresentation(ElementImpl element, IdentifiableEntity ie)
461
			throws ParseException {
462

    
463
		// create <Representation> element
464
		ElementImpl representation = new ElementImpl(document, REPRESENTATION);
465
		element.appendChild(representation);
466
		buildLabel(representation, ie.getTitleCache());
467

    
468
		Set<Annotation> annotations = ie.getAnnotations();
469
		Iterator iterator = annotations.iterator();
470
		String detailText = null;
471
		if (iterator.hasNext()) {
472
			Annotation annotation = (Annotation) iterator.next();
473
			detailText = annotation.getText();
474
		}
475

    
476
		if (detailText != null && !detailText.equals("")) {
477
			ElementImpl detail = new ElementImpl(document, DETAIL);
478
			detail.appendChild(document.createTextNode(detailText));
479
			representation.appendChild(detail);
480
		}
481

    
482
		if (ie instanceof DefinedTermBase) {
483
			DefinedTermBase dtb = (DefinedTermBase) ie;
484
			Set<Media> rm = dtb.getMedia();
485

    
486
			if (rm != null && rm.size() > 0) {
487
				ElementImpl mediaObject;
488

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

    
525
	}
526

    
527
	/**
528
	 * Builds RevisionData associated with the Dataset
529
	 */
530
	public void buildRevisionData(ElementImpl dataset, IDatabase database)
531
			throws ParseException {
532

    
533
		// <RevisionData>
534
		// <Creators>
535
		// <Agent role="aut" ref="a1"/>
536
		// <Agent role="aut" ref="a2"/>
537
		// <Agent role="edt" ref="a3"/>
538
		// </Creators>
539
		// <DateModified>2006-04-08T00:00:00</DateModified>
540
		// </RevisionData>
541

    
542
		ElementImpl revisionData = new ElementImpl(document, REVISION_DATA);
543

    
544
		// authors
545
		TeamOrPersonBase authors = database.getAuthorship();
546
		// TeamOrPersonBase editors = database.getUpdatedBy();
547

    
548
		if ((authors != null)) { // || (editors != null)) {
549
			ElementImpl creators = new ElementImpl(document, CREATORS);
550
			if (authors != null) {
551
				buildRefAgent(creators, authors, "aut");
552
			}
553
			// if (editors != null) {
554
			// buildRefAgent(creators, editors, "edt");
555
			// }
556
			revisionData.appendChild(creators);
557
		}
558

    
559
		buildDateModified(revisionData, database);
560

    
561
		dataset.appendChild(revisionData);
562
	}
563

    
564
	/**
565
	 * Builds ModifiedDate associated with RevisionData
566
	 */
567
	public void buildDateModified(ElementImpl revisionData, IDatabase database)
568
			throws ParseException {
569

    
570
		// <DateModified>2006-04-08T00:00:00</DateModified>
571

    
572
		if (((Reference) database).getUpdated() != null) {
573
			ElementImpl dateModified = new ElementImpl(document, DATE_MODIFIED);
574

    
575
			DateTime c = ((Reference) database).getUpdated();
576
			DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
577

    
578
			String date = fmt.print(c);
579
			dateModified.appendChild(document.createTextNode(date));
580

    
581
			revisionData.appendChild(dateModified);
582
		}
583

    
584
	}
585

    
586
	/**
587
	 * Builds IPRStatements associated with the Dataset
588
	 */
589
	public void buildIPRStatements(ElementImpl dataset, IDatabase database)
590
			throws ParseException {
591

    
592
		// <IPRStatements>
593
		// <IPRStatement role="Copyright">
594
		// <Label xml:lang="en-au">(c) 2003-2006 Centre for Occasional
595
		// Botany.</Label>
596
		// </IPRStatement>
597
		// </IPRStatements>
598

    
599
		if (database.getRights() != null) {
600
			// create IPRStatements
601
			ElementImpl iprStatements = new ElementImpl(document,
602
					IPR_STATEMENTS);
603
			dataset.appendChild(iprStatements);
604

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

    
616
	}
617

    
618
	/**
619
	 * Creates a Label element
620
	 *
621
	 * @param base
622
	 * @param element
623
	 */
624
	public void buildLabel(ElementImpl element, String text) {
625
		ElementImpl label = new ElementImpl(document, LABEL);
626
		label.appendChild(document.createTextNode(text));
627
		element.appendChild(label);
628
	}
629

    
630
	// ################
631
	// # GENERIC BRICKS #
632
	// ################
633

    
634
	/**
635
	 * Builds TaxonNames associated with the Dataset
636
	 */
637
	public void buildTaxonNames(ElementImpl dataset) throws ParseException {
638

    
639
		// <TaxonNames>
640
		// <TaxonName id="t1" uri="urn:lsid:authority:namespace:my-own-id">
641
		// <Representation>
642
		// <Label xml:lang="la">Viola hederacea Labill.</Label>
643
		// </Representation>
644
		// </TaxonName>
645
		// </TaxonNames>
646

    
647
		if (cdmSource.getTaxonomicNames() != null) {
648
			ElementImpl elTaxonNames = new ElementImpl(document, TAXON_NAMES);
649

    
650
			for (int i = 0; i < cdmSource.getTaxonomicNames().size(); i++) {
651
				ElementImpl elTaxonName = new ElementImpl(document, TAXON_NAME);
652
				TaxonName tnb = cdmSource.getTaxonomicNames().get(i);
653

    
654
				taxonNamesCount = buildReference(tnb, taxonNames, ID,
655
						elTaxonName, "t", taxonNamesCount);
656

    
657
				buildRepresentation(elTaxonName, tnb);
658

    
659
				elTaxonNames.appendChild(elTaxonName);
660
			}
661

    
662
			dataset.appendChild(elTaxonNames);
663
		}
664

    
665
	}
666

    
667
	public void buildDescriptiveConcepts(ElementImpl dataset)
668
			throws ParseException {
669

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

    
726
	/**
727
	 * Builds Characters associated with the Dataset
728
	 */
729
	public void buildCharacters(ElementImpl dataset) throws ParseException {
730

    
731
		if (cdmSource.getTerms() != null) {
732
			ElementImpl elCharacters = new ElementImpl(document, CHARACTERS);
733

    
734
			int f = cdmSource.getTerms().size();
735
			for (int i = 0; i < f; i++) {
736
				if (cdmSource.getTerms().get(i) instanceof Feature) {
737
					Feature character = (Feature) cdmSource.getTerms().get(i);
738
					if (character.isSupportsQuantitativeData()) {
739
						ElementImpl elQuantitativeCharacter = new ElementImpl(
740
								document, QUANTITATIVE_CHARACTER);
741
						charactersCount = buildReference(character, characters,
742
								ID, elQuantitativeCharacter, "c",
743
								charactersCount);
744
						buildRepresentation(elQuantitativeCharacter, character);
745
						elCharacters.appendChild(elQuantitativeCharacter);
746
					}
747

    
748
					if (character.isSupportsCategoricalData()) {
749
						ElementImpl elCategoricalCharacter = new ElementImpl(
750
								document, CATEGORICAL_CHARACTER);
751
						charactersCount = buildReference(character, characters,
752
								ID, elCategoricalCharacter, "c",
753
								charactersCount);
754
						buildRepresentation(elCategoricalCharacter, character);
755

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

    
794
			dataset.appendChild(elCharacters);
795
		}
796

    
797
	}
798

    
799
	public void buildCodedDescriptions(ElementImpl dataset)
800
			throws ParseException {
801

    
802
		if (cdmSource.getTaxa() != null) {
803
			ElementImpl elCodedDescriptions = new ElementImpl(document,
804
					CODED_DESCRIPTIONS);
805

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

    
825
			dataset.appendChild(elCodedDescriptions);
826
		}
827

    
828
	}
829

    
830
	/**
831
	 * Builds Scope associated with a CodedDescription
832
	 */
833
	public void buildScope(ElementImpl element,
834
			TaxonDescription taxonDescription) throws ParseException {
835

    
836
		// <Scope>
837
		// <TaxonName ref="t1"/>
838
		// <Citation ref="p1" location="p. 30"/>
839
		// </Scope>
840

    
841
		ElementImpl scope = new ElementImpl(document, SCOPE);
842

    
843
		Taxon taxon = taxonDescription.getTaxon();
844
		if (taxon != null) {
845
			TaxonName taxonName = taxon.getName();
846
			if (taxonName != null) {
847
				String ref = taxonNames.get(taxonName);
848
				if (!ref.equals("")) {
849
					ElementImpl taxonNameEl = new ElementImpl(document,
850
							TAXON_NAME);
851
					taxonNameEl.setAttribute(REF, ref);
852
					scope.appendChild(taxonNameEl);
853
				}
854
			}
855
		}
856

    
857
		Set<Reference> descriptionSources = new HashSet<Reference>();
858
		for (IdentifiableSource source : taxonDescription.getSources()){
859
			descriptionSources.add(source.getCitation());
860
		}
861
		for (Iterator<Reference> rb = descriptionSources.iterator(); rb.hasNext();) {
862
			Reference descriptionSource = rb.next();
863
			if (descriptionSource.getType().equals(ReferenceType.Article)) {
864

    
865
				ElementImpl citation = new ElementImpl(document, CITATION);
866
				articlesCount = buildReference(descriptionSource, articles,
867
						REF, citation, "p", articlesCount);
868

    
869
				Set<Annotation> annotations = descriptionSource.getAnnotations();
870
				for (Iterator<Annotation> a = annotations.iterator(); a.hasNext();) {
871
					Annotation annotation = a.next();
872
					AnnotationType annotationType = annotation.getAnnotationType();
873
					if (annotationType != null) {
874
						String type = annotationType.getLabel();
875
						if (type.equals("location")) {
876
							citation.setAttribute("location",annotation.getText());
877
						}
878
					}
879
				}
880

    
881
				scope.appendChild(citation);
882
			}
883
		}
884

    
885
		element.appendChild(scope);
886
	}
887

    
888
	/**
889
	 * Builds SummaryData associated with a CodedDescription
890
	 */
891
	public void buildSummaryData(ElementImpl element,
892
			TaxonDescription taxonDescription) throws ParseException {
893

    
894
		// <SummaryData>
895
		// <Categorical ref="c4">
896
		// <State ref="s3"/>
897
		// <State ref="s4"/>
898
		// </Categorical>
899

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

    
921
	/**
922
	 * Builds Categorical associated with a SummaryData
923
	 */
924
	public void buildCategorical(ElementImpl element,
925
			CategoricalData categoricalData) throws ParseException {
926

    
927
		// <SummaryData>
928
		// <Categorical ref="c4">
929
		// <State ref="s3"/>
930
		// <State ref="s4"/>
931
		// </Categorical>
932

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

    
946
	/**
947
	 * Builds State associated with a Categorical
948
	 */
949
	public void buildState(ElementImpl element, State s) throws ParseException {
950

    
951
		// <SummaryData>
952
		// <Categorical ref="c4">
953
		// <State ref="s3"/>
954
		// <State ref="s4"/>
955
		// </Categorical>
956

    
957
		ElementImpl state = new ElementImpl(document, STATE);
958
		buildReference(s, states, REF, state, "s", statesCount);
959
		element.appendChild(state);
960
	}
961

    
962
	/**
963
	 * Builds Quantitative associated with a SummaryData
964
	 */
965
	public void buildQuantitative(ElementImpl element,
966
			QuantitativeData quantitativeData) throws ParseException {
967

    
968
		// <Quantitative ref="c2">
969
		// <Measure type="Min" value="2.3"></Measure>
970
		// <Measure type="Mean" value="5.1"/>
971
		// <Measure type="Max" value="7.9"/>
972
		// <Measure type="SD" value="1.3"/>
973
		// <Measure type="N" value="20"/>
974
		// </Quantitative>
975

    
976
		ElementImpl quantitative = new ElementImpl(document, QUANTITATIVE);
977
		Feature feature = quantitativeData.getFeature();
978
		buildReference(feature, characters, REF, quantitative, "c",
979
				charactersCount);
980
		Set<StatisticalMeasurementValue> statisticalValues = quantitativeData
981
				.getStatisticalValues();
982
		for (Iterator<StatisticalMeasurementValue> smv = statisticalValues
983
				.iterator(); smv.hasNext();) {
984
			StatisticalMeasurementValue statisticalValue = smv.next();
985
			buildMeasure(quantitative, statisticalValue);
986
		}
987
		element.appendChild(quantitative);
988
	}
989

    
990
	/**
991
	 * Builds Measure associated with a Quantitative
992
	 */
993
	public void buildMeasure(ElementImpl element,
994
			StatisticalMeasurementValue statisticalValue) throws ParseException {
995

    
996
		// <Quantitative ref="c2">
997
		// <Measure type="Min" value="2.3"></Measure>
998
		// <Measure type="Mean" value="5.1"/>
999
		// <Measure type="Max" value="7.9"/>
1000
		// <Measure type="SD" value="1.3"/>
1001
		// <Measure type="N" value="20"/>
1002
		// </Quantitative>
1003

    
1004
		ElementImpl measure = new ElementImpl(document, MEASURE);
1005
		StatisticalMeasure type = statisticalValue.getType();
1006
		String label = type.getLabel();
1007
		if (label.equals("Average")) {
1008
			measure.setAttribute("type", "Mean");
1009
		} else if (label.equals("StandardDeviation")) {
1010
			measure.setAttribute("type", "SD");
1011
		} else if (label.equals("SampleSize")) {
1012
			measure.setAttribute("type", "N");
1013
		} else {
1014
			measure.setAttribute("type", label);
1015
		}
1016
		BigDecimal value = statisticalValue.getValue();
1017
		measure.setAttribute("value", String.valueOf(value));
1018
		element.appendChild(measure);
1019
	}
1020

    
1021
	/**
1022
	 * Builds TextChar associated with a SummaryData
1023
	 */
1024
	public void buildTextChar(ElementImpl element, TextData textData)
1025
			throws ParseException {
1026

    
1027
		// <TextChar ref="c3">
1028
		// <Content>Free form text</Content>
1029
		// </TextChar>
1030

    
1031
		ElementImpl textChar = new ElementImpl(document, TEXT_CHAR);
1032
		Feature feature = textData.getFeature();
1033
		buildReference(feature, characters, REF, textChar, "c", charactersCount);
1034
		Map<Language, LanguageString> multilanguageText = textData
1035
				.getMultilanguageText();
1036
		for (Language language : multilanguageText.keySet()) {
1037
			LanguageString languageString = multilanguageText.get(language);
1038
			buildContent(textChar, languageString);
1039
		}
1040
		element.appendChild(textChar);
1041
	}
1042

    
1043
	/**
1044
	 * Builds Content associated with a TextChar
1045
	 */
1046
	public void buildContent(ElementImpl element, LanguageString languageString)
1047
			throws ParseException {
1048

    
1049
		// <TextChar ref="c3">
1050
		// <Content>Free form text</Content>
1051
		// </TextChar>
1052

    
1053
		ElementImpl content = new ElementImpl(document, CONTENT);
1054
		Language language = languageString.getLanguage();
1055
		String text = languageString.getText();
1056
		if (!language.getIso639_1().equals(defaultLanguage.getIso639_1())) {
1057
			content.setAttribute("xml:lang", language.getIso639_1());
1058
		}
1059
		content.setTextContent(text);
1060
		element.appendChild(content);
1061
	}
1062

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

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

    
1143
	/**
1144
	 * Builds Agents associated with the Dataset
1145
	 */
1146
	public void buildAgents(ElementImpl dataset) throws ParseException {
1147

    
1148
		if (cdmSource.getAgents() != null) {
1149
			ElementImpl elAgents = new ElementImpl(document, AGENTS);
1150

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

    
1174
			dataset.appendChild(elAgents);
1175
		}
1176
	}
1177

    
1178
	public void buildCharacterTrees(ElementImpl dataset) throws ParseException {
1179

    
1180
		if (cdmSource.getFeatureData() != null) {
1181
			ElementImpl elChartrees = new ElementImpl(document, CHARACTER_TREES);
1182

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

    
1207
	public void buildClassifications(ElementImpl dataset) throws ParseException {
1208

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

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

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

    
1344
	public void buildMediaObjects(ElementImpl dataset) throws ParseException {
1345

    
1346
		if (cdmSource.getMedia() != null) {
1347
			ElementImpl elMediaObjects = new ElementImpl(document,
1348
					MEDIA_OBJECTS);
1349

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

    
1382
	public void buildPublications(ElementImpl dataset) throws ParseException {
1383

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

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

    
1484
	public void buildGeographicAreas(ElementImpl dataset) {
1485
		if (cdmSource.getTerms() != null) {
1486
			ElementImpl elGeographicAreas = new ElementImpl(document,
1487
					"GeographicAreas");
1488

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

    
1507
				}
1508
			}
1509
			dataset.appendChild(elGeographicAreas);
1510
		}
1511
	}
1512

    
1513
	public void buildSpecimens(ElementImpl dataset) throws ParseException {
1514

    
1515
		if (cdmSource.getOccurrences() != null) {
1516
			ElementImpl elSpecimens = new ElementImpl(document, "Specimens");
1517

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

    
1530
	}
1531

    
1532
}
(3-3/5)