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.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.log4j.Logger;
28
import org.apache.xerces.dom.DocumentImpl;
29
import org.apache.xerces.dom.ElementImpl;
30
import org.apache.xerces.impl.xpath.regex.ParseException;
31
import org.apache.xml.serialize.DOMSerializer;
32
import org.apache.xml.serialize.OutputFormat;
33
import org.apache.xml.serialize.XMLSerializer;
34
import org.joda.time.DateTime;
35
import org.joda.time.format.DateTimeFormatter;
36
import org.joda.time.format.ISODateTimeFormat;
37
import org.springframework.util.ResourceUtils;
38
import org.xml.sax.SAXException;
39

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

    
87
/**
88
 * Writes the SDD XML file.
89
 *
90
 * @author h.fradin
91
 * @since 10.12.2008
92
 * @version 1.0
93
 */
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<FeatureNode, String> featureNodes = new HashMap<>();
107
	private final Map<Feature, String> descriptiveConcepts = new HashMap<>();
108
	private final Map<TaxonDescription, String> codedDescriptions = new HashMap<>();
109
	private final Map<Media, String> medias = new HashMap<>();
110
	private final Map<State, String> states = new HashMap<>();
111
	private final Map<Reference, String> articles = new HashMap<>();
112
	private final Map<VersionableEntity, String> featuretrees = new HashMap<>();
113
	private final Map<DefinedTerm, String> modifiers = new HashMap<>();
114
	private final Map<TaxonNode, String> taxonNodes = new HashMap<>();
115
	private final Map<NamedArea, String> namedAreas = new HashMap<>();
116
	private final Map<DerivedUnit, String> specimens = new HashMap<>();
117

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

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

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

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

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

    
203
	public SDDDocumentBuilder() throws SAXException, IOException {
204

    
205
		document = new DocumentImpl();
206

    
207
	}
208

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

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

    
218
	}
219

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

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

    
229
	}
230

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

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

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

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

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

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

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

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

    
267
		FileOutputStream fos = new FileOutputStream(sddDestination);
268

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

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

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

    
276
		writer.close();
277
	}
278

    
279
	// #############
280
	// # BUILD DOM #
281
	// #############
282

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

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

    
301
		buildTechnicalMetadata(baselement);
302

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

    
315
	// #############
316
	// # BUILD DOM #
317
	// #############
318

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

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

    
351
		baselement.appendChild(technicalMetadata);
352
	}
353

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

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

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

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

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

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

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

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

    
416
	}
417

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

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

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

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

    
444
			}
445
		}
446

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

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

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

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

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

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

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

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

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

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

    
532
	}
533

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

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

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

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

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

    
566
		buildDateModified(revisionData, database);
567

    
568
		dataset.appendChild(revisionData);
569
	}
570

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

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

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

    
582
			DateTime c = ((Reference) database).getUpdated();
583
			DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
584

    
585
			String date = fmt.print(c);
586
			dateModified.appendChild(document.createTextNode(date));
587

    
588
			revisionData.appendChild(dateModified);
589
		}
590

    
591
	}
592

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

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

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

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

    
623
	}
624

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

    
637
	// ################
638
	// # GENERIC BRICKS #
639
	// ################
640

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

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

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

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

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

    
664
				buildRepresentation(elTaxonName, tnb);
665

    
666
				elTaxonNames.appendChild(elTaxonName);
667
			}
668

    
669
			dataset.appendChild(elTaxonNames);
670
		}
671

    
672
	}
673

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

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

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

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

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

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

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

    
801
			dataset.appendChild(elCharacters);
802
		}
803

    
804
	}
805

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

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

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

    
832
			dataset.appendChild(elCodedDescriptions);
833
		}
834

    
835
	}
836

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

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

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

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

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

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

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

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

    
892
		element.appendChild(scope);
893
	}
894

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1536
	}
1537

    
1538
}
(3-3/5)