1
|
/**
|
2
|
* Copyright (C) 2009 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.markup;
|
11
|
|
12
|
import java.net.MalformedURLException;
|
13
|
import java.net.URISyntaxException;
|
14
|
import java.net.URL;
|
15
|
import java.util.ArrayList;
|
16
|
import java.util.Arrays;
|
17
|
import java.util.HashMap;
|
18
|
import java.util.HashSet;
|
19
|
import java.util.LinkedList;
|
20
|
import java.util.List;
|
21
|
import java.util.Map;
|
22
|
import java.util.Queue;
|
23
|
import java.util.Set;
|
24
|
import java.util.UUID;
|
25
|
|
26
|
import javax.xml.stream.FactoryConfigurationError;
|
27
|
import javax.xml.stream.Location;
|
28
|
import javax.xml.stream.XMLEventReader;
|
29
|
import javax.xml.stream.XMLStreamException;
|
30
|
import javax.xml.stream.events.Attribute;
|
31
|
import javax.xml.stream.events.StartElement;
|
32
|
import javax.xml.stream.events.XMLEvent;
|
33
|
|
34
|
import org.apache.commons.lang.StringUtils;
|
35
|
import org.apache.log4j.Logger;
|
36
|
import org.springframework.beans.factory.annotation.Autowired;
|
37
|
import org.springframework.security.access.PermissionEvaluator;
|
38
|
import org.springframework.security.authentication.AuthenticationManager;
|
39
|
import org.springframework.security.core.Authentication;
|
40
|
import org.springframework.stereotype.Component;
|
41
|
import org.springframework.transaction.TransactionStatus;
|
42
|
|
43
|
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
|
44
|
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade.DerivedUnitType;
|
45
|
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeCacheStrategy;
|
46
|
import eu.etaxonomy.cdm.common.CdmUtils;
|
47
|
import eu.etaxonomy.cdm.io.common.ICdmIO;
|
48
|
import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
|
49
|
import eu.etaxonomy.cdm.io.markup.UnmatchedLeads.UnmatchedLeadsKey;
|
50
|
import eu.etaxonomy.cdm.model.agent.AgentBase;
|
51
|
import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
|
52
|
import eu.etaxonomy.cdm.model.agent.Team;
|
53
|
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
|
54
|
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
|
55
|
import eu.etaxonomy.cdm.model.common.Annotation;
|
56
|
import eu.etaxonomy.cdm.model.common.AnnotationType;
|
57
|
import eu.etaxonomy.cdm.model.common.CdmBase;
|
58
|
import eu.etaxonomy.cdm.model.common.Extension;
|
59
|
import eu.etaxonomy.cdm.model.common.ExtensionType;
|
60
|
import eu.etaxonomy.cdm.model.common.Figure;
|
61
|
import eu.etaxonomy.cdm.model.common.Language;
|
62
|
import eu.etaxonomy.cdm.model.common.TermVocabulary;
|
63
|
import eu.etaxonomy.cdm.model.common.TimePeriod;
|
64
|
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
|
65
|
import eu.etaxonomy.cdm.model.description.Distribution;
|
66
|
import eu.etaxonomy.cdm.model.description.Feature;
|
67
|
import eu.etaxonomy.cdm.model.description.KeyStatement;
|
68
|
import eu.etaxonomy.cdm.model.description.PolytomousKey;
|
69
|
import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;
|
70
|
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
|
71
|
import eu.etaxonomy.cdm.model.description.TaxonDescription;
|
72
|
import eu.etaxonomy.cdm.model.description.TextData;
|
73
|
import eu.etaxonomy.cdm.model.location.NamedArea;
|
74
|
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
|
75
|
import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;
|
76
|
import eu.etaxonomy.cdm.model.media.Media;
|
77
|
import eu.etaxonomy.cdm.model.name.CultivarPlantName;
|
78
|
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
|
79
|
import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
|
80
|
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
|
81
|
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
|
82
|
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
|
83
|
import eu.etaxonomy.cdm.model.name.NonViralName;
|
84
|
import eu.etaxonomy.cdm.model.name.Rank;
|
85
|
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
|
86
|
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
|
87
|
import eu.etaxonomy.cdm.model.occurrence.Collection;
|
88
|
import eu.etaxonomy.cdm.model.occurrence.DerivedUnitBase;
|
89
|
import eu.etaxonomy.cdm.model.occurrence.FieldObservation;
|
90
|
import eu.etaxonomy.cdm.model.occurrence.Specimen;
|
91
|
import eu.etaxonomy.cdm.model.reference.IArticle;
|
92
|
import eu.etaxonomy.cdm.model.reference.IJournal;
|
93
|
import eu.etaxonomy.cdm.model.reference.Reference;
|
94
|
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
|
95
|
import eu.etaxonomy.cdm.model.reference.ReferenceType;
|
96
|
import eu.etaxonomy.cdm.model.taxon.Classification;
|
97
|
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
|
98
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
99
|
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
|
100
|
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
|
101
|
import eu.etaxonomy.cdm.strategy.parser.NameTypeParser;
|
102
|
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
|
103
|
import eu.etaxonomy.cdm.strategy.parser.SpecimenTypeParser;
|
104
|
import eu.etaxonomy.cdm.strategy.parser.SpecimenTypeParser.TypeInfo;
|
105
|
|
106
|
/**
|
107
|
* @author a.mueller
|
108
|
*
|
109
|
*/
|
110
|
@Component
|
111
|
public class MarkupDocumentImport extends MarkupImportBase implements ICdmIO<MarkupImportState> {
|
112
|
private static final String FREQUENCY = "frequency";
|
113
|
|
114
|
private static final String TAXONTYPE = "taxontype";
|
115
|
|
116
|
private static final String DEDICATION = "dedication";
|
117
|
|
118
|
private static final String QUOTE = "quote";
|
119
|
|
120
|
private static final Logger logger = Logger.getLogger(MarkupDocumentImport.class);
|
121
|
|
122
|
private static final boolean CREATE_NEW = true;
|
123
|
private static final boolean IS_IMAGE_GALLERY = true;
|
124
|
private static final boolean NO_IMAGE_GALLERY = false;
|
125
|
|
126
|
private static final String ACCEPTED = "accepted";
|
127
|
private static final String ACCEPTED_NAME = "acceptedName";
|
128
|
private static final String ADDENDA = "addenda";
|
129
|
private static final String ALTERNATEPUBTITLE = "alternatepubtitle";
|
130
|
private static final String ALTERNATIVE_COLLECTION_TYPE_STATUS = "alternativeCollectionTypeStatus";
|
131
|
private static final String ALTERNATIVE_COLLECTOR = "alternativeCollector";
|
132
|
private static final String ALTERNATIVE_FIELD_NUM = "alternativeFieldNum";
|
133
|
private static final String ALTITUDE = "altitude";
|
134
|
private static final String ANNOTATION = "annotation";
|
135
|
private static final String AUTHOR = "author";
|
136
|
private static final String BIBLIOGRAPHY = "bibliography";
|
137
|
private static final String BIOGRAPHIES = "biographies";
|
138
|
private static final String BOLD = "bold";
|
139
|
private static final String BR = "br";
|
140
|
private static final String CHAR = "char";
|
141
|
private static final String CITATION = "citation";
|
142
|
private static final String COLLECTION_TYPE_STATUS = "collectionTypeStatus";
|
143
|
private static final String COLLECTOR = "collector";
|
144
|
private static final String COORDINATES = "coordinates";
|
145
|
private static final String COUPLET = "couplet";
|
146
|
private static final String DATES = "dates";
|
147
|
private static final String DEFAULT_MEDIA_URL = "defaultMediaUrl";
|
148
|
private static final String DESTROYED = "destroyed";
|
149
|
private static final String DETAILS = "details";
|
150
|
private static final String DISTRIBUTION_LIST = "distributionList";
|
151
|
private static final String DISTRIBUTION_LOCALITY = "distributionLocality";
|
152
|
private static final String EDITION = "edition";
|
153
|
private static final String EDITORS = "editors";
|
154
|
private static final String FEATURE = "feature";
|
155
|
private static final String FIGURE = "figure";
|
156
|
private static final String FIGURE_LEGEND = "figureLegend";
|
157
|
private static final String FIGURE_PART = "figurePart";
|
158
|
private static final String FIGURE_REF = "figureRef";
|
159
|
private static final String FIGURE_TITLE = "figureTitle";
|
160
|
private static final String FOOTNOTE = "footnote";
|
161
|
private static final String FOOTNOTE_REF = "footnoteRef";
|
162
|
private static final String FOOTNOTE_STRING = "footnoteString";
|
163
|
private static final String FIELD_NUM = "fieldNum";
|
164
|
private static final String FULL_NAME = "fullName";
|
165
|
private static final String FULL_TYPE = "fullType";
|
166
|
private static final String GATHERING = "gathering";
|
167
|
private static final String HEADING = "heading";
|
168
|
private static final String HABITAT = "habitat";
|
169
|
private static final String HABITAT_LIST = "habitatList";
|
170
|
private static final String HOMONYM = "homonym";
|
171
|
private static final String HOMOTYPES = "homotypes";
|
172
|
private static final String ID = "id";
|
173
|
private static final String INFRANK = "infrank";
|
174
|
private static final String INFRAUT = "infraut";
|
175
|
private static final String INFRPARAUT = "infrparaut";
|
176
|
private static final String IS_SPOTCHARACTERS = "isSpotcharacters";
|
177
|
private static final String ISSUE = "issue";
|
178
|
private static final String ITALICS = "italics";
|
179
|
private static final String KEY = "key";
|
180
|
private static final String KEY_TITLE = "keyTitle";
|
181
|
private static final String KEYNOTES = "keynotes";
|
182
|
private static final String LIFE_CYCLE_PERIODS = "lifeCyclePeriods";
|
183
|
private static final String LOCALITY = "locality";
|
184
|
private static final String LOST = "lost";
|
185
|
private static final String META_DATA = "metaData";
|
186
|
private static final String NAME = "name";
|
187
|
private static final String NAME_TYPE = "nameType";
|
188
|
private static final String NOM = "nom";
|
189
|
private static final String NOMENCLATURE = "nomenclature";
|
190
|
private static final String NOT_FOUND = "notFound";
|
191
|
private static final String NOT_SEEN = "notSeen";
|
192
|
private static final String NOTES = "notes";
|
193
|
private static final String NUM = "num";
|
194
|
private static final String ORIGINAL_DETERMINATION = "originalDetermination";
|
195
|
private static final String PARAUT = "paraut";
|
196
|
private static final String PUBFULLNAME = "pubfullname";
|
197
|
private static final String PUBLICATION = "publication";
|
198
|
private static final String PUBNAME = "pubname";
|
199
|
private static final String PUBTITLE = "pubtitle";
|
200
|
private static final String PUBTYPE = "pubtype";
|
201
|
private static final String QUESTION = "question";
|
202
|
private static final String RANK = "rank";
|
203
|
private static final String REF = "ref";
|
204
|
private static final String REF_NUM = "refNum";
|
205
|
private static final String REF_PART = "refPart";
|
206
|
private static final String REFERENCE = "reference";
|
207
|
private static final String REFERENCES = "references";
|
208
|
private static final String TAXON = "taxon";
|
209
|
private static final String TAXONTITLE = "taxontitle";
|
210
|
private static final String TEXT = "text";
|
211
|
private static final String TEXT_SECTION = "textSection";
|
212
|
private static final String TO_COUPLET = "toCouplet";
|
213
|
private static final String TO_KEY = "toKey";
|
214
|
private static final String TO_TAXON = "toTaxon";
|
215
|
private static final String TYPE = "type";
|
216
|
private static final String TYPE_STATUS = "typeStatus";
|
217
|
private static final String TREATMENT = "treatment";
|
218
|
private static final String SERIALS_ABBREVIATIONS = "serialsAbbreviations";
|
219
|
private static final String SPECIMEN_TYPE = "specimenType";
|
220
|
private static final String STATUS = "status";
|
221
|
private static final String STRING = "string";
|
222
|
private static final String SUB_HEADING = "subHeading";
|
223
|
private static final String SUB_COLLECTION = "subCollection";
|
224
|
private static final String SYNONYM = "synonym";
|
225
|
private static final String UNKNOWN = "unknown";
|
226
|
private static final String URL = "url";
|
227
|
private static final String USAGE = "usage";
|
228
|
private static final String VOLUME = "volume";
|
229
|
private static final String WRITER = "writer";
|
230
|
private static final String YEAR = "year";
|
231
|
|
232
|
private NonViralNameParserImpl parser = new NonViralNameParserImpl();
|
233
|
|
234
|
// TODO make part of state, but state is renewed when invoking the import a
|
235
|
// second time
|
236
|
private UnmatchedLeads unmatchedLeads;
|
237
|
|
238
|
// TODO remove preliminary
|
239
|
@Autowired
|
240
|
private AuthenticationManager authenticationManager;
|
241
|
private Authentication authentication;
|
242
|
private PermissionEvaluator permissionEvaluator;
|
243
|
|
244
|
public MarkupDocumentImport() {
|
245
|
super();
|
246
|
System.out.println("TODO remove preliminary authentication");
|
247
|
// UsernamePasswordAuthenticationToken token = new
|
248
|
// UsernamePasswordAuthenticationToken("admin", "0000");
|
249
|
// authentication = authenticationManager.authenticate(token);
|
250
|
// SecurityContext context = SecurityContextHolder.getContext();
|
251
|
// context.setAuthentication(authentication);
|
252
|
// permissionEvaluator = new CdmPermissionEvaluator();
|
253
|
}
|
254
|
|
255
|
@Override
|
256
|
public boolean doCheck(MarkupImportState state) {
|
257
|
state.setCheck(true);
|
258
|
doInvoke(state);
|
259
|
state.setCheck(false);
|
260
|
return state.isSuccess();
|
261
|
}
|
262
|
|
263
|
@Override
|
264
|
public void doInvoke(MarkupImportState state) {
|
265
|
fireProgressEvent("Start import markup document", "Before start of document");
|
266
|
|
267
|
Queue<CdmBase> outputStream = new LinkedList<CdmBase>();
|
268
|
|
269
|
TransactionStatus tx = startTransaction();
|
270
|
// FIXME reset state
|
271
|
doAllTheOldOtherStuff(state);
|
272
|
|
273
|
// START
|
274
|
try {
|
275
|
// StAX
|
276
|
XMLEventReader reader = getStaxReader(state);
|
277
|
state.setReader(reader);
|
278
|
// start document
|
279
|
if (!validateStartOfDocument(reader)) {
|
280
|
state.setUnsuccessfull();
|
281
|
return;
|
282
|
}
|
283
|
|
284
|
// publication
|
285
|
String elName = PUBLICATION;
|
286
|
boolean hasPublication = false;
|
287
|
|
288
|
while (reader.hasNext()) {
|
289
|
XMLEvent nextEvent = reader.nextEvent();
|
290
|
if (isStartingElement(nextEvent, elName)) {
|
291
|
handlePublication(state, reader, nextEvent, elName);
|
292
|
hasPublication = true;
|
293
|
} else if (nextEvent.isEndDocument()) {
|
294
|
if (!hasPublication) {
|
295
|
String message = "No publication root element found";
|
296
|
fireWarningEvent(message, nextEvent, 8);
|
297
|
}
|
298
|
// done
|
299
|
} else {
|
300
|
fireSchemaConflictEventExpectedStartTag(elName, reader);
|
301
|
}
|
302
|
}
|
303
|
commitTransaction(tx);
|
304
|
|
305
|
// //SAX
|
306
|
// ImportHandlerBase handler= new PublicationHandler(this);
|
307
|
// parseSAX(state, handler);
|
308
|
|
309
|
} catch (FactoryConfigurationError e1) {
|
310
|
fireWarningEvent("Some error occurred while setting up xml factory. Data can't be imported", "Start", 16);
|
311
|
state.setUnsuccessfull();
|
312
|
} catch (XMLStreamException e1) {
|
313
|
fireWarningEvent("An XMLStreamException occurred while parsing. Data can't be imported", "Start", 16);
|
314
|
state.setUnsuccessfull();
|
315
|
// } catch (ParserConfigurationException e) {
|
316
|
// fireWarningEvent("A ParserConfigurationException occurred while parsing. Data can't be imported",
|
317
|
// "Start", 16);
|
318
|
// } catch (SAXException e) {
|
319
|
// fireWarningEvent("A SAXException occurred while parsing. Data can't be imported",
|
320
|
// "Start", 16);
|
321
|
// } catch (IOException e) {
|
322
|
// fireWarningEvent("An IO exception occurred while parsing. Data can't be imported",
|
323
|
// "Start", 16);
|
324
|
|
325
|
}
|
326
|
|
327
|
return;
|
328
|
|
329
|
}
|
330
|
|
331
|
private void handlePublication(MarkupImportState state,
|
332
|
XMLEventReader reader, XMLEvent currentEvent, String elName)
|
333
|
throws XMLStreamException {
|
334
|
|
335
|
// attributes
|
336
|
StartElement element = currentEvent.asStartElement();
|
337
|
Map<String, Attribute> attributes = getAttributes(element);
|
338
|
handleUnexpectedAttributes(element.getLocation(), attributes,
|
339
|
"noNamespaceSchemaLocation");
|
340
|
|
341
|
while (reader.hasNext()) {
|
342
|
XMLEvent event = readNoWhitespace(reader);
|
343
|
// TODO cardinality of alternative
|
344
|
if (event.isEndElement()) {
|
345
|
if (isEndingElement(event, elName)) {
|
346
|
return;
|
347
|
} else {
|
348
|
if (isEndingElement(event, BIOGRAPHIES)) {
|
349
|
// NOT YET IMPLEMENTED
|
350
|
popUnimplemented(event.asEndElement());
|
351
|
} else if (isEndingElement(event, REFERENCES)) {
|
352
|
// NOT YET IMPLEMENTED
|
353
|
popUnimplemented(event.asEndElement());
|
354
|
} else if (isEndingElement(event, TEXT_SECTION)) {
|
355
|
// NOT YET IMPLEMENTED
|
356
|
popUnimplemented(event.asEndElement());
|
357
|
} else if (isEndingElement(event, ADDENDA)) {
|
358
|
// NOT YET IMPLEMENTED
|
359
|
popUnimplemented(event.asEndElement());
|
360
|
} else {
|
361
|
handleUnexpectedElement(event);
|
362
|
}
|
363
|
}
|
364
|
} else if (event.isStartElement()) {
|
365
|
if (isStartingElement(event, META_DATA)) {
|
366
|
handleMetaData(state, reader, event);
|
367
|
} else if (isStartingElement(event, TREATMENT)) {
|
368
|
handleTreatment(state, reader, event);
|
369
|
} else if (isStartingElement(event, BIOGRAPHIES)) {
|
370
|
handleNotYetImplementedElement(event);
|
371
|
} else if (isStartingElement(event, REFERENCES)) {
|
372
|
handleNotYetImplementedElement(event);
|
373
|
} else if (isStartingElement(event, TEXT_SECTION)) {
|
374
|
handleNotYetImplementedElement(event);
|
375
|
} else if (isStartingElement(event, ADDENDA)) {
|
376
|
handleNotYetImplementedElement(event);
|
377
|
} else {
|
378
|
handleUnexpectedStartElement(event);
|
379
|
}
|
380
|
} else {
|
381
|
handleUnexpectedElement(event);
|
382
|
}
|
383
|
}
|
384
|
throw new IllegalStateException("Publication has no ending element");
|
385
|
}
|
386
|
|
387
|
private void handleMetaData(MarkupImportState state, XMLEventReader reader,
|
388
|
XMLEvent parentEvent) throws XMLStreamException {
|
389
|
checkNoAttributes(parentEvent);
|
390
|
|
391
|
while (reader.hasNext()) {
|
392
|
XMLEvent next = readNoWhitespace(reader);
|
393
|
if (isMyEndingElement(next, parentEvent)) {
|
394
|
return;
|
395
|
} else if (isStartingElement(next, DEFAULT_MEDIA_URL)) {
|
396
|
String baseUrl = getCData(state, reader, next);
|
397
|
try {
|
398
|
new URL(baseUrl);
|
399
|
state.setBaseMediaUrl(baseUrl);
|
400
|
} catch (MalformedURLException e) {
|
401
|
String message = "defaultMediaUrl '%s' is not a valid URL";
|
402
|
message = String.format(message, baseUrl);
|
403
|
fireWarningEvent(message, next, 8);
|
404
|
}
|
405
|
} else {
|
406
|
handleUnexpectedElement(next);
|
407
|
}
|
408
|
}
|
409
|
throw new IllegalStateException("MetaData has no ending element");
|
410
|
|
411
|
}
|
412
|
|
413
|
private void handleTreatment(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
414
|
checkNoAttributes(parentEvent);
|
415
|
Taxon lastTaxon = null;
|
416
|
while (reader.hasNext()) {
|
417
|
XMLEvent next = readNoWhitespace(reader);
|
418
|
if (isStartingElement(next, TAXON)) {
|
419
|
Taxon thisTaxon = handleTaxon(state, reader, next.asStartElement());
|
420
|
doTaxonRelation(state, thisTaxon, lastTaxon, parentEvent.getLocation());
|
421
|
lastTaxon = thisTaxon;
|
422
|
// TODO for imports spanning multiple documents ?? Still needed?
|
423
|
state.getConfig().setLastTaxonUuid(lastTaxon.getUuid());
|
424
|
} else if (isMyEndingElement(next, parentEvent)) {
|
425
|
Set<PolytomousKeyNode> keyNodesToSave = state.getPolytomousKeyNodesToSave();
|
426
|
//better save the key then the nodes
|
427
|
Set<PolytomousKey> keySet = new HashSet<PolytomousKey>();
|
428
|
for (PolytomousKeyNode node : keyNodesToSave){
|
429
|
PolytomousKey key = node.getKey();
|
430
|
keySet.add(key);
|
431
|
}
|
432
|
save(keySet, state);
|
433
|
//unmatched key leads
|
434
|
UnmatchedLeads unmatched = state.getUnmatchedLeads();
|
435
|
if (unmatched.size() > 0){
|
436
|
String message = "The following key leads are unmatched: %s";
|
437
|
message = String.format(message, state.getUnmatchedLeads().toString());
|
438
|
fireWarningEvent(message, next, 6);
|
439
|
}
|
440
|
// save(keyNodesToSave, state);
|
441
|
|
442
|
return;
|
443
|
} else {
|
444
|
handleUnexpectedElement(next);
|
445
|
}
|
446
|
}
|
447
|
return;
|
448
|
}
|
449
|
|
450
|
/**
|
451
|
* @param taxon
|
452
|
* @param lastTaxon
|
453
|
*/
|
454
|
private void doTaxonRelation(MarkupImportState state, Taxon taxon,
|
455
|
Taxon lastTaxon, Location dataLocation) {
|
456
|
|
457
|
Classification tree = makeTree(state, dataLocation);
|
458
|
if (lastTaxon == null) {
|
459
|
tree.addChildTaxon(taxon, null, null, null);
|
460
|
return;
|
461
|
}
|
462
|
Rank thisRank = taxon.getName().getRank();
|
463
|
Rank lastRank = lastTaxon.getName().getRank();
|
464
|
if (lastTaxon.getTaxonNodes().size() > 0) {
|
465
|
TaxonNode lastNode = lastTaxon.getTaxonNodes().iterator().next();
|
466
|
if (thisRank.isLower(lastRank)) {
|
467
|
lastNode.addChildTaxon(taxon, null, null, null);
|
468
|
fillMissingEpithetsForTaxa(lastTaxon, taxon);
|
469
|
} else if (thisRank.equals(lastRank)) {
|
470
|
TaxonNode parent = lastNode.getParent();
|
471
|
if (parent != null) {
|
472
|
parent.addChildTaxon(taxon, null, null, null);
|
473
|
fillMissingEpithetsForTaxa(parent.getTaxon(), taxon);
|
474
|
} else {
|
475
|
tree.addChildTaxon(taxon, null, null, null);
|
476
|
}
|
477
|
} else if (thisRank.isHigher(lastRank)) {
|
478
|
doTaxonRelation(state, taxon, lastNode.getParent().getTaxon(),
|
479
|
dataLocation);
|
480
|
// TaxonNode parentNode = handleTaxonRelation(state, taxon,
|
481
|
// lastNode.getParent().getTaxon());
|
482
|
// parentNode.addChildTaxon(taxon, null, null, null);
|
483
|
}
|
484
|
} else {
|
485
|
|
486
|
String message = "Last taxon has no node";
|
487
|
fireWarningEvent(message, makeLocationStr(dataLocation), 6);
|
488
|
}
|
489
|
}
|
490
|
|
491
|
/**
|
492
|
* @param state
|
493
|
* @param dataLocation
|
494
|
* @return
|
495
|
*/
|
496
|
private Classification makeTree(MarkupImportState state, Location dataLocation) {
|
497
|
Classification result = state.getTree(null);
|
498
|
if (result == null) {
|
499
|
UUID uuid = state.getConfig().getClassificationUuid();
|
500
|
if (uuid == null) {
|
501
|
String message = "No classification uuid is defined";
|
502
|
fireWarningEvent(message, makeLocationStr(dataLocation), 6);
|
503
|
result = createNewClassification(state);
|
504
|
} else {
|
505
|
result = getClassificationService().find(uuid);
|
506
|
if (result == null) {
|
507
|
result = createNewClassification(state);
|
508
|
result.setUuid(uuid);
|
509
|
}
|
510
|
}
|
511
|
state.putTree(null, result);
|
512
|
}
|
513
|
save(result, state);
|
514
|
return result;
|
515
|
}
|
516
|
|
517
|
private Classification createNewClassification(MarkupImportState state) {
|
518
|
Classification result;
|
519
|
result = Classification.NewInstance(state.getConfig().getClassificationTitle());
|
520
|
state.putTree(null, result);
|
521
|
return result;
|
522
|
}
|
523
|
|
524
|
private Taxon handleTaxon(MarkupImportState state, XMLEventReader reader, StartElement parentEvent) throws XMLStreamException {
|
525
|
// TODO progress monitoring
|
526
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
527
|
Taxon taxon = createTaxonAndName(state, attributes);
|
528
|
state.setCurrentTaxon(taxon);
|
529
|
|
530
|
boolean hasTitle = false;
|
531
|
boolean hasNomenclature = false;
|
532
|
String taxonTitle = null;
|
533
|
|
534
|
while (reader.hasNext()) {
|
535
|
XMLEvent next = readNoWhitespace(reader);
|
536
|
if (next.isEndElement()) {
|
537
|
if (isMyEndingElement(next, parentEvent)) {
|
538
|
checkMandatoryElement(hasTitle, parentEvent, TAXONTITLE);
|
539
|
checkMandatoryElement(hasNomenclature, parentEvent, NOMENCLATURE);
|
540
|
handleUnexpectedAttributes(parentEvent.getLocation(),attributes);
|
541
|
|
542
|
makeKeyNodes(state, parentEvent, taxonTitle);
|
543
|
state.setCurrentTaxon(null);
|
544
|
state.setCurrentTaxonNum(null);
|
545
|
save(taxon, state);
|
546
|
return taxon;
|
547
|
} else {
|
548
|
if (isEndingElement(next, HEADING)) {
|
549
|
// NOT YET IMPLEMENTED
|
550
|
popUnimplemented(next.asEndElement());
|
551
|
} else if (isEndingElement(next, TEXT_SECTION)) {
|
552
|
// NOT YET IMPLEMENTED
|
553
|
popUnimplemented(next.asEndElement());
|
554
|
} else if (isEndingElement(next, REFERENCES)) {
|
555
|
// NOT YET IMPLEMENTED
|
556
|
popUnimplemented(next.asEndElement());
|
557
|
} else {
|
558
|
handleUnexpectedEndElement(next.asEndElement());
|
559
|
}
|
560
|
}
|
561
|
} else if (next.isStartElement()) {
|
562
|
if (isStartingElement(next, HEADING)) {
|
563
|
handleNotYetImplementedElement(next);
|
564
|
} else if (isStartingElement(next, TAXONTITLE)) {
|
565
|
taxonTitle = handleTaxonTitle(state, reader, next);
|
566
|
hasTitle = true;
|
567
|
} else if (isStartingElement(next, WRITER)) {
|
568
|
makeKeyWriter(state, reader, taxon, taxonTitle, next);
|
569
|
} else if (isStartingElement(next, TEXT_SECTION)) {
|
570
|
handleNotYetImplementedElement(next);
|
571
|
} else if (isStartingElement(next, KEY)) {
|
572
|
handleKey(state, reader, next);
|
573
|
} else if (isStartingElement(next, NOMENCLATURE)) {
|
574
|
handleNomenclature(state, reader, next);
|
575
|
hasNomenclature = true;
|
576
|
} else if (isStartingElement(next, FEATURE)) {
|
577
|
handleFeature(state, reader, next);
|
578
|
} else if (isStartingElement(next, NOTES)) {
|
579
|
// TODO is this the correct way to handle notes?
|
580
|
String note = handleNotes(state, reader, next);
|
581
|
|
582
|
UUID notesUuid;
|
583
|
try {
|
584
|
notesUuid = state.getTransformer().getFeatureUuid(
|
585
|
"notes");
|
586
|
Feature feature = getFeature(state, notesUuid, "Notes",
|
587
|
"Notes", "note", null);
|
588
|
TextData textData = TextData.NewInstance(feature);
|
589
|
textData.putText(Language.DEFAULT(), note);
|
590
|
TaxonDescription description = getTaxonDescription(
|
591
|
taxon, false, true);
|
592
|
description.addElement(textData);
|
593
|
} catch (UndefinedTransformerMethodException e) {
|
594
|
String message = "getFeatureUuid method not yet implemented";
|
595
|
fireWarningEvent(message, next, 8);
|
596
|
}
|
597
|
} else if (isStartingElement(next, REFERENCES)) {
|
598
|
handleNotYetImplementedElement(next);
|
599
|
} else if (isStartingElement(next, FIGURE)) {
|
600
|
handleFigure(state, reader, next);
|
601
|
} else if (isStartingElement(next, FOOTNOTE)) {
|
602
|
FootnoteDataHolder footnote = handleFootnote(state, reader,
|
603
|
next);
|
604
|
if (footnote.isRef()) {
|
605
|
String message = "Ref footnote not implemented here";
|
606
|
fireWarningEvent(message, next, 4);
|
607
|
} else {
|
608
|
registerGivenFootnote(state, footnote);
|
609
|
}
|
610
|
} else {
|
611
|
handleUnexpectedStartElement(next);
|
612
|
}
|
613
|
} else {
|
614
|
handleUnexpectedElement(next);
|
615
|
}
|
616
|
}
|
617
|
throw new IllegalStateException("<Taxon> has no closing tag");
|
618
|
}
|
619
|
|
620
|
private void makeKeyNodes(MarkupImportState state, XMLEvent event, String taxonTitle) {
|
621
|
Taxon taxon = state.getCurrentTaxon();
|
622
|
String num = state.getCurrentTaxonNum();
|
623
|
|
624
|
String nameString = CdmBase.deproxy(taxon.getName(), NonViralName.class).getNameCache();
|
625
|
// String nameString = taxonTitle;
|
626
|
|
627
|
//try to find matching lead nodes
|
628
|
UnmatchedLeadsKey leadsKey = UnmatchedLeadsKey.NewInstance(num, nameString);
|
629
|
Set<PolytomousKeyNode> matchingNodes = handleMatchingNodes(state, taxon, leadsKey);
|
630
|
|
631
|
if (num != null){//same without using the num
|
632
|
UnmatchedLeadsKey noNumLeadsKey = UnmatchedLeadsKey.NewInstance("", nameString);
|
633
|
Set<PolytomousKeyNode> noNumMatchingNodes = handleMatchingNodes(state, taxon, noNumLeadsKey);
|
634
|
if(noNumMatchingNodes.size() > 0){
|
635
|
String message ="Taxon matches additional key node when not considering <num> attribute in taxontitle. This may be correct but may also indicate an error.";
|
636
|
fireWarningEvent(message, event, 1);
|
637
|
}
|
638
|
}
|
639
|
//report missing match, if num exists
|
640
|
if (matchingNodes.isEmpty() && num != null){
|
641
|
String message = "Taxon has <num> attribute in taxontitle but no matching key nodes exist: %s, Key: %s";
|
642
|
message = String.format(message, num, leadsKey.toString());
|
643
|
fireWarningEvent(message, event, 1);
|
644
|
}
|
645
|
|
646
|
}
|
647
|
|
648
|
private Set<PolytomousKeyNode> handleMatchingNodes(MarkupImportState state, Taxon taxon, UnmatchedLeadsKey leadsKey) {
|
649
|
Set<PolytomousKeyNode> matchingNodes = state.getUnmatchedLeads().getNodes(leadsKey);
|
650
|
for (PolytomousKeyNode matchingNode : matchingNodes){
|
651
|
state.getUnmatchedLeads().removeNode(leadsKey, matchingNode);
|
652
|
matchingNode.setTaxon(taxon);
|
653
|
state.getPolytomousKeyNodesToSave().add(matchingNode);
|
654
|
}
|
655
|
return matchingNodes;
|
656
|
}
|
657
|
|
658
|
private void handleKey(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
659
|
// attributes
|
660
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
661
|
String isSpotcharacters = getAndRemoveAttributeValue(attributes, IS_SPOTCHARACTERS);
|
662
|
if (isNotBlank(isSpotcharacters) ) {
|
663
|
//TODO isSpotcharacters
|
664
|
String message = "Attribute isSpotcharacters not yet implemented for <key>";
|
665
|
fireWarningEvent(message, parentEvent, 4);
|
666
|
}
|
667
|
|
668
|
PolytomousKey key = PolytomousKey.NewInstance();
|
669
|
key.addTaxonomicScope(state.getCurrentTaxon());
|
670
|
state.setCurrentKey(key);
|
671
|
|
672
|
boolean isFirstCouplet = true;
|
673
|
while (reader.hasNext()) {
|
674
|
XMLEvent next = readNoWhitespace(reader);
|
675
|
if (isMyEndingElement(next, parentEvent)) {
|
676
|
save(key, state);
|
677
|
state.setCurrentKey(null);
|
678
|
return;
|
679
|
} else if (isEndingElement(next, KEYNOTES)){
|
680
|
popUnimplemented(next.asEndElement());
|
681
|
} else if (isStartingElement(next, KEY_TITLE)) {
|
682
|
handleKeyTitle(state, reader, next);
|
683
|
} else if (isStartingElement(next, KEYNOTES)) {
|
684
|
//TODO
|
685
|
handleNotYetImplementedElement(next);
|
686
|
} else if (isStartingElement(next, COUPLET)) {
|
687
|
PolytomousKeyNode node = null;
|
688
|
if (isFirstCouplet){
|
689
|
node = key.getRoot();
|
690
|
isFirstCouplet = false;
|
691
|
}
|
692
|
handleCouplet(state, reader, next, node);
|
693
|
} else {
|
694
|
handleUnexpectedElement(next);
|
695
|
}
|
696
|
}
|
697
|
throw new IllegalStateException("<key> has no closing tag");
|
698
|
}
|
699
|
|
700
|
/**
|
701
|
* @param state
|
702
|
* @param reader
|
703
|
* @param key
|
704
|
* @param next
|
705
|
* @throws XMLStreamException
|
706
|
*/
|
707
|
private void handleKeyTitle(MarkupImportState state, XMLEventReader reader, XMLEvent next) throws XMLStreamException {
|
708
|
PolytomousKey key = state.getCurrentKey();
|
709
|
String keyTitle = getCData(state, reader, next);
|
710
|
String standardTitles = "(?i)(Key\\sto\\sthe\\s(genera|species|varieties|forms))";
|
711
|
|
712
|
if (isNotBlank(keyTitle) ){
|
713
|
if (!state.getConfig().isReplaceStandardKeyTitles() || ! keyTitle.matches(standardTitles)){
|
714
|
key.setTitleCache(keyTitle, true);
|
715
|
}
|
716
|
}
|
717
|
}
|
718
|
|
719
|
private void handleCouplet(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, PolytomousKeyNode parentNode) throws XMLStreamException {
|
720
|
String num = getOnlyAttribute(parentEvent, NUM, true);
|
721
|
List<PolytomousKeyNode> childList = new ArrayList<PolytomousKeyNode>();
|
722
|
|
723
|
while (reader.hasNext()) {
|
724
|
XMLEvent next = readNoWhitespace(reader);
|
725
|
if (isMyEndingElement(next, parentEvent)) {
|
726
|
completeCouplet(state, parentEvent, parentNode, num, childList);
|
727
|
return;
|
728
|
} else if (isStartingElement(next, QUESTION)) {
|
729
|
handleQuestion(state, reader, next, childList);
|
730
|
} else if (isStartingElement(next, KEYNOTES)) {
|
731
|
//TODO
|
732
|
handleNotYetImplementedElement(next);
|
733
|
} else if (isEndingElement(next, KEYNOTES)) {
|
734
|
//TODO
|
735
|
popUnimplemented(next.asEndElement());
|
736
|
} else {
|
737
|
handleUnexpectedElement(next);
|
738
|
}
|
739
|
}
|
740
|
throw new IllegalStateException("<couplet> has no closing tag");
|
741
|
}
|
742
|
|
743
|
/**
|
744
|
* @param state
|
745
|
* @param parentEvent
|
746
|
* @param parentNode
|
747
|
* @param num
|
748
|
* @param childList
|
749
|
*/
|
750
|
private void completeCouplet(MarkupImportState state, XMLEvent parentEvent,
|
751
|
PolytomousKeyNode parentNode, String num,
|
752
|
List<PolytomousKeyNode> childList) {
|
753
|
if (parentNode != null){
|
754
|
for (PolytomousKeyNode childNode : childList){
|
755
|
parentNode.addChild(childNode);
|
756
|
}
|
757
|
}else if (isNotBlank(num)){
|
758
|
UnmatchedLeadsKey unmatchedKey = UnmatchedLeadsKey.NewInstance(state.getCurrentKey(), num);
|
759
|
Set<PolytomousKeyNode> nodes = state.getUnmatchedLeads().getNodes(unmatchedKey);
|
760
|
for(PolytomousKeyNode nodeToMatch: nodes){
|
761
|
for (PolytomousKeyNode childNode : childList){
|
762
|
nodeToMatch.addChild(childNode);
|
763
|
}
|
764
|
state.getUnmatchedLeads().removeNode(unmatchedKey, nodeToMatch);
|
765
|
}
|
766
|
}else{
|
767
|
String message = "Parent num could not be matched. Please check if num (%s) is correct";
|
768
|
message = String.format(message, num);
|
769
|
fireWarningEvent(message, parentEvent, 6);
|
770
|
}
|
771
|
}
|
772
|
|
773
|
private void handleQuestion(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, List<PolytomousKeyNode> nodesList) throws XMLStreamException {
|
774
|
// attributes
|
775
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
776
|
//needed only for data lineage
|
777
|
String questionNum = getAndRemoveRequiredAttributeValue(parentEvent, attributes, NUM);
|
778
|
|
779
|
PolytomousKeyNode myNode = PolytomousKeyNode.NewInstance();
|
780
|
myNode.setKey(state.getCurrentKey()); //to avoid NPE while computing num in PolytomousKeyNode in case this node is not matched correctly with a parent
|
781
|
nodesList.add(myNode);
|
782
|
|
783
|
while (reader.hasNext()) {
|
784
|
XMLEvent next = readNoWhitespace(reader);
|
785
|
if (isMyEndingElement(next, parentEvent)) {
|
786
|
return;
|
787
|
} else if (isStartingElement(next, TEXT)) {
|
788
|
String text = getCData(state, reader, next);
|
789
|
KeyStatement statement = KeyStatement.NewInstance(text);
|
790
|
myNode.setStatement(statement);
|
791
|
} else if (isStartingElement(next, COUPLET)) {
|
792
|
//TODO test
|
793
|
handleCouplet(state, reader, next, myNode);
|
794
|
} else if (isStartingElement(next, TO_COUPLET)) {
|
795
|
handleToCouplet(state, reader, next, myNode);
|
796
|
} else if (isStartingElement(next, TO_TAXON)) {
|
797
|
handleToTaxon(state, reader, next, myNode);
|
798
|
|
799
|
} else if (isStartingElement(next, TO_KEY)) {
|
800
|
//TODO
|
801
|
handleNotYetImplementedElement(next);
|
802
|
} else if (isEndingElement(next, TO_KEY)){
|
803
|
//TODO
|
804
|
popUnimplemented(next.asEndElement());
|
805
|
} else if (isStartingElement(next, KEYNOTES)) {
|
806
|
//TODO
|
807
|
handleNotYetImplementedElement(next);
|
808
|
} else if (isEndingElement(next, KEYNOTES)){
|
809
|
//TODO
|
810
|
popUnimplemented(next.asEndElement());
|
811
|
} else {
|
812
|
handleUnexpectedElement(next);
|
813
|
}
|
814
|
}
|
815
|
throw new IllegalStateException("<question> has no closing tag");
|
816
|
}
|
817
|
|
818
|
private void handleToCouplet(MarkupImportState state, XMLEventReader reader, XMLEvent next, PolytomousKeyNode node) throws XMLStreamException {
|
819
|
String num = getOnlyAttribute(next, NUM, true);
|
820
|
String cData = getCData(state, reader, next, false);
|
821
|
if (isNotBlank(cData) && ! cData.equals(num)){
|
822
|
String message = "CData ('%s') not handled in <toCouplet>";
|
823
|
message = String.format(message, cData);
|
824
|
fireWarningEvent(message, next, 4);
|
825
|
}
|
826
|
UnmatchedLeadsKey unmatched = UnmatchedLeadsKey.NewInstance(state.getCurrentKey(), num);
|
827
|
state.getUnmatchedLeads().addKey(unmatched, node);
|
828
|
}
|
829
|
|
830
|
private void handleToTaxon(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, PolytomousKeyNode node) throws XMLStreamException {
|
831
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
832
|
String num = getAndRemoveAttributeValue(attributes, NUM);
|
833
|
String taxonStr = getCData(state, reader, parentEvent, false);
|
834
|
//TODO ?
|
835
|
taxonStr = makeTaxonKey(taxonStr, state.getCurrentTaxon());
|
836
|
UnmatchedLeadsKey unmatched = UnmatchedLeadsKey.NewInstance(num, taxonStr);
|
837
|
state.getUnmatchedLeads().addKey(unmatched, node);
|
838
|
return;
|
839
|
}
|
840
|
|
841
|
private String makeTaxonKey(String strGoto, Taxon taxon) {
|
842
|
String result = "";
|
843
|
if (strGoto == null){
|
844
|
return "";
|
845
|
}
|
846
|
|
847
|
NonViralName<?> name = CdmBase.deproxy(taxon.getName(), NonViralName.class);
|
848
|
String strGenusName = name.getGenusOrUninomial();
|
849
|
|
850
|
|
851
|
strGoto = strGoto.replaceAll("\\([^\\(\\)]*\\)", ""); //replace all brackets
|
852
|
strGoto = strGoto.replaceAll("\\s+", " "); //replace multiple whitespaces by exactly one whitespace
|
853
|
|
854
|
strGoto = strGoto.trim();
|
855
|
String[] split = strGoto.split("\\s");
|
856
|
for (int i = 0; i<split.length; i++){
|
857
|
String single = split[i];
|
858
|
if (isGenusAbbrev(single, strGenusName)){
|
859
|
split[i] = strGenusName;
|
860
|
}
|
861
|
if (isInfraSpecificMarker(single)){
|
862
|
String strSpeciesEpi = name.getSpecificEpithet();
|
863
|
if (isBlank(result)){
|
864
|
result += strGenusName + " " + strSpeciesEpi;
|
865
|
}
|
866
|
}
|
867
|
result = (result + " " + split[i]).trim();
|
868
|
}
|
869
|
return result;
|
870
|
}
|
871
|
|
872
|
|
873
|
private boolean isInfraSpecificMarker(String single) {
|
874
|
try {
|
875
|
if (Rank.getRankByAbbreviation(single).isInfraSpecific()){
|
876
|
return true;
|
877
|
}else{
|
878
|
return false;
|
879
|
}
|
880
|
} catch (UnknownCdmTypeException e) {
|
881
|
return false;
|
882
|
}
|
883
|
}
|
884
|
|
885
|
private boolean isGenusAbbrev(String single, String strGenusName) {
|
886
|
if (! single.matches("[A-Z]\\.?")) {
|
887
|
return false;
|
888
|
}else if (single.length() == 0 || strGenusName == null || strGenusName.length() == 0){
|
889
|
return false;
|
890
|
}else{
|
891
|
return single.charAt(0) == strGenusName.charAt(0);
|
892
|
}
|
893
|
}
|
894
|
|
895
|
/**
|
896
|
* @param state
|
897
|
* @param reader
|
898
|
* @param taxon
|
899
|
* @param taxonTitle
|
900
|
* @param next
|
901
|
* @throws XMLStreamException
|
902
|
*/
|
903
|
private void makeKeyWriter(MarkupImportState state, XMLEventReader reader, Taxon taxon, String taxonTitle, XMLEvent next) throws XMLStreamException {
|
904
|
WriterDataHolder writer = handleWriter(state, reader, next);
|
905
|
taxon.addExtension(writer.extension);
|
906
|
// TODO what if taxonTitle comes later
|
907
|
if (StringUtils.isNotBlank(taxonTitle)
|
908
|
&& writer.extension != null) {
|
909
|
Reference<?> sec = ReferenceFactory.newBookSection();
|
910
|
sec.setTitle(taxonTitle);
|
911
|
TeamOrPersonBase<?> author = createAuthor(writer.writer);
|
912
|
sec.setAuthorTeam(author);
|
913
|
sec.setInReference(state.getConfig()
|
914
|
.getSourceReference());
|
915
|
taxon.setSec(sec);
|
916
|
registerFootnotes(state, sec, writer.footnotes);
|
917
|
} else {
|
918
|
String message = "No taxontitle exists for writer";
|
919
|
fireWarningEvent(message, next, 6);
|
920
|
}
|
921
|
}
|
922
|
|
923
|
private String handleNotes(MarkupImportState state, XMLEventReader reader,
|
924
|
XMLEvent parentEvent) throws XMLStreamException {
|
925
|
checkNoAttributes(parentEvent);
|
926
|
|
927
|
String text = "";
|
928
|
while (reader.hasNext()) {
|
929
|
XMLEvent next = readNoWhitespace(reader);
|
930
|
if (isMyEndingElement(next, parentEvent)) {
|
931
|
return text;
|
932
|
} else if (next.isEndElement()) {
|
933
|
if (isEndingElement(next, HEADING)) {
|
934
|
popUnimplemented(next.asEndElement());
|
935
|
} else if (isEndingElement(next, WRITER)) {
|
936
|
popUnimplemented(next.asEndElement());
|
937
|
} else if (isEndingElement(next, NUM)) {
|
938
|
popUnimplemented(next.asEndElement());
|
939
|
} else {
|
940
|
handleUnexpectedEndElement(next.asEndElement());
|
941
|
}
|
942
|
} else if (next.isStartElement()) {
|
943
|
if (isStartingElement(next, HEADING)) {
|
944
|
handleNotYetImplementedElement(next);
|
945
|
} else if (isStartingElement(next, SUB_HEADING)) {
|
946
|
String subheading = getCData(state, reader, next).trim();
|
947
|
if (! isNoteHeading(subheading)) {
|
948
|
fireNotYetImplementedElement(next.getLocation(), next.asStartElement().getName(), 0);
|
949
|
}
|
950
|
} else if (isStartingElement(next, WRITER)) {
|
951
|
handleNotYetImplementedElement(next);
|
952
|
} else if (isStartingElement(next, NUM)) {
|
953
|
handleNotYetImplementedElement(next);
|
954
|
} else if (isStartingElement(next, STRING)) {
|
955
|
// TODO why multiple strings in schema?
|
956
|
text = makeNotesString(state, reader, text, next);
|
957
|
} else {
|
958
|
handleUnexpectedStartElement(next.asStartElement());
|
959
|
}
|
960
|
} else {
|
961
|
handleUnexpectedElement(next);
|
962
|
}
|
963
|
}
|
964
|
throw new IllegalStateException("<Notes> has no closing tag");
|
965
|
}
|
966
|
|
967
|
/**
|
968
|
* @param state
|
969
|
* @param reader
|
970
|
* @param text
|
971
|
* @param next
|
972
|
* @return
|
973
|
* @throws XMLStreamException
|
974
|
*/
|
975
|
private String makeNotesString(MarkupImportState state, XMLEventReader reader, String text, XMLEvent next) throws XMLStreamException {
|
976
|
Map<String, String> stringMap = handleString(state, reader, next, null);
|
977
|
if (stringMap.size() == 0){
|
978
|
String message = "No text available in <notes>";
|
979
|
fireWarningEvent(message, next, 4);
|
980
|
}else if (stringMap.size() > 1){
|
981
|
String message = "Subheadings not yet supported in <notes>";
|
982
|
fireWarningEvent(message, next, 4);
|
983
|
}else{
|
984
|
String firstSubheading = stringMap.keySet().iterator().next();
|
985
|
if ( firstSubheading != null && ! isNoteHeading (firstSubheading) ) {
|
986
|
String message = "Subheadings not yet supported in <notes>";
|
987
|
fireWarningEvent(message, next, 4);
|
988
|
}
|
989
|
}
|
990
|
for (String subheading : stringMap.keySet()){
|
991
|
text += subheading;
|
992
|
text += stringMap.get(subheading);
|
993
|
}
|
994
|
return text;
|
995
|
}
|
996
|
|
997
|
private boolean isNoteHeading(String heading) {
|
998
|
String excludePattern = "(i?)(Notes?):?";
|
999
|
return heading.matches(excludePattern);
|
1000
|
}
|
1001
|
|
1002
|
/**
|
1003
|
* @param state
|
1004
|
* @param attributes
|
1005
|
*/
|
1006
|
private Taxon createTaxonAndName(MarkupImportState state,
|
1007
|
Map<String, Attribute> attributes) {
|
1008
|
NonViralName<?> name;
|
1009
|
Rank rank = Rank.SPECIES(); // default
|
1010
|
boolean isCultivar = checkAndRemoveAttributeValue(attributes, CLASS,
|
1011
|
"cultivated");
|
1012
|
if (isCultivar) {
|
1013
|
name = CultivarPlantName.NewInstance(rank);
|
1014
|
} else {
|
1015
|
name = createNameByCode(state, rank);
|
1016
|
}
|
1017
|
Taxon taxon = Taxon.NewInstance(name, state.getConfig()
|
1018
|
.getSourceReference());
|
1019
|
if (checkAndRemoveAttributeValue(attributes, CLASS, "dubious")) {
|
1020
|
taxon.setDoubtful(true);
|
1021
|
} else if (checkAndRemoveAttributeValue(attributes, CLASS, "excluded")) {
|
1022
|
taxon.setExcluded(true);
|
1023
|
}
|
1024
|
// TODO insufficient, new, expected
|
1025
|
handleNotYetImplementedAttribute(attributes, CLASS);
|
1026
|
// From old version
|
1027
|
// MarkerType markerType = getMarkerType(state, attrValue);
|
1028
|
// if (markerType == null){
|
1029
|
// logger.warn("Class attribute value for taxon not yet supported: " +
|
1030
|
// attrValue);
|
1031
|
// }else{
|
1032
|
// taxon.addMarker(Marker.NewInstance(markerType, true));
|
1033
|
// }
|
1034
|
|
1035
|
// save(name, state);
|
1036
|
// save(taxon, state);
|
1037
|
return taxon;
|
1038
|
}
|
1039
|
|
1040
|
/**
|
1041
|
* @param state
|
1042
|
* @param rank
|
1043
|
* @return
|
1044
|
*/
|
1045
|
private NonViralName<?> createNameByCode(MarkupImportState state, Rank rank) {
|
1046
|
NonViralName<?> name;
|
1047
|
NomenclaturalCode nc = makeNomenclaturalCode(state);
|
1048
|
name = (NonViralName<?>) nc.getNewTaxonNameInstance(rank);
|
1049
|
return name;
|
1050
|
}
|
1051
|
|
1052
|
/**
|
1053
|
* @param state
|
1054
|
* @return
|
1055
|
*/
|
1056
|
private NomenclaturalCode makeNomenclaturalCode(MarkupImportState state) {
|
1057
|
NomenclaturalCode nc = state.getConfig().getNomenclaturalCode();
|
1058
|
if (nc == null) {
|
1059
|
nc = NomenclaturalCode.ICBN; // default;
|
1060
|
}
|
1061
|
return nc;
|
1062
|
}
|
1063
|
|
1064
|
private String handleTaxonTitle(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
1065
|
//attributes
|
1066
|
String text = "";
|
1067
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
1068
|
String rankAttr = getAndRemoveAttributeValue(attributes, RANK);
|
1069
|
Rank rank = makeRank(state, rankAttr, false);
|
1070
|
String num = getAndRemoveAttributeValue(attributes, NUM);
|
1071
|
state.setCurrentTaxonNum(num);
|
1072
|
checkNoAttributes(attributes, parentEvent);
|
1073
|
|
1074
|
// TODO handle attributes
|
1075
|
while (reader.hasNext()) {
|
1076
|
XMLEvent next = readNoWhitespace(reader);
|
1077
|
if (next.isEndElement()) {
|
1078
|
if (isMyEndingElement(next, parentEvent)) {
|
1079
|
Taxon taxon = state.getCurrentTaxon();
|
1080
|
String titleText = null;
|
1081
|
if (checkMandatoryText(text, parentEvent)) {
|
1082
|
titleText = normalize(text);
|
1083
|
UUID uuidTitle = MarkupTransformer.uuidTaxonTitle;
|
1084
|
ExtensionType titleExtension = this.getExtensionType(state, uuidTitle, "Taxon Title ","taxon title", "title");
|
1085
|
taxon.addExtension(titleText, titleExtension);
|
1086
|
}
|
1087
|
taxon.getName().setRank(rank);
|
1088
|
// TODO check title exists
|
1089
|
return titleText;
|
1090
|
} else {
|
1091
|
if (isEndingElement(next, FOOTNOTE)) {
|
1092
|
// NOT YET IMPLEMENTED
|
1093
|
popUnimplemented(next.asEndElement());
|
1094
|
} else {
|
1095
|
handleUnexpectedEndElement(next.asEndElement());
|
1096
|
state.setUnsuccessfull();
|
1097
|
}
|
1098
|
}
|
1099
|
} else if (next.isStartElement()) {
|
1100
|
if (isStartingElement(next, FOOTNOTE)) {
|
1101
|
handleNotYetImplementedElement(next);
|
1102
|
} else {
|
1103
|
handleUnexpectedStartElement(next);
|
1104
|
state.setUnsuccessfull();
|
1105
|
}
|
1106
|
} else if (next.isCharacters()) {
|
1107
|
text += next.asCharacters().getData();
|
1108
|
|
1109
|
} else {
|
1110
|
handleUnexpectedElement(next);
|
1111
|
state.setUnsuccessfull();
|
1112
|
}
|
1113
|
}
|
1114
|
return null;
|
1115
|
|
1116
|
}
|
1117
|
|
1118
|
private WriterDataHolder handleWriter(MarkupImportState state,
|
1119
|
XMLEventReader reader, XMLEvent parentEvent)
|
1120
|
throws XMLStreamException {
|
1121
|
String text = "";
|
1122
|
checkNoAttributes(parentEvent);
|
1123
|
WriterDataHolder dataHolder = new WriterDataHolder();
|
1124
|
List<FootnoteDataHolder> footnotes = new ArrayList<FootnoteDataHolder>();
|
1125
|
|
1126
|
// TODO handle attributes
|
1127
|
while (reader.hasNext()) {
|
1128
|
XMLEvent next = readNoWhitespace(reader);
|
1129
|
if (isMyEndingElement(next, parentEvent)) {
|
1130
|
text = CdmUtils.removeBrackets(text);
|
1131
|
if (checkMandatoryText(text, parentEvent)) {
|
1132
|
text = normalize(text);
|
1133
|
dataHolder.writer = text;
|
1134
|
dataHolder.footnotes = footnotes;
|
1135
|
|
1136
|
// Extension
|
1137
|
UUID uuidWriterExtension = MarkupTransformer.uuidWriterExtension;
|
1138
|
ExtensionType writerExtensionType = this
|
1139
|
.getExtensionType(state, uuidWriterExtension,
|
1140
|
"Writer", "writer", "writer");
|
1141
|
Extension extension = Extension.NewInstance();
|
1142
|
extension.setType(writerExtensionType);
|
1143
|
extension.setValue(text);
|
1144
|
dataHolder.extension = extension;
|
1145
|
|
1146
|
// Annotation
|
1147
|
UUID uuidWriterAnnotation = MarkupTransformer.uuidWriterAnnotation;
|
1148
|
AnnotationType writerAnnotationType = this.getAnnotationType(state, uuidWriterAnnotation, "Writer", "writer", "writer", null);
|
1149
|
Annotation annotation = Annotation.NewInstance(text, writerAnnotationType, Language.DEFAULT());
|
1150
|
dataHolder.annotation = annotation;
|
1151
|
|
1152
|
return dataHolder;
|
1153
|
} else {
|
1154
|
return null;
|
1155
|
}
|
1156
|
} else if (isStartingElement(next, FOOTNOTE_REF)) {
|
1157
|
FootnoteDataHolder footNote = handleFootnoteRef(state, reader, next);
|
1158
|
if (footNote.isRef()) {
|
1159
|
footnotes.add(footNote);
|
1160
|
} else {
|
1161
|
logger.warn("Non ref footnotes not yet impelemnted");
|
1162
|
}
|
1163
|
} else if (next.isCharacters()) {
|
1164
|
text += next.asCharacters().getData();
|
1165
|
|
1166
|
} else {
|
1167
|
handleUnexpectedElement(next);
|
1168
|
state.setUnsuccessfull();
|
1169
|
}
|
1170
|
}
|
1171
|
throw new IllegalStateException("<writer> has no end tag");
|
1172
|
}
|
1173
|
|
1174
|
private void registerFootnotes(MarkupImportState state,
|
1175
|
AnnotatableEntity entity, List<FootnoteDataHolder> footnotes) {
|
1176
|
for (FootnoteDataHolder footNote : footnotes) {
|
1177
|
registerFootnoteDemand(state, entity, footNote);
|
1178
|
}
|
1179
|
}
|
1180
|
|
1181
|
private void registerGivenFootnote(MarkupImportState state,
|
1182
|
FootnoteDataHolder footnote) {
|
1183
|
state.registerFootnote(footnote);
|
1184
|
Set<AnnotatableEntity> demands = state.getFootnoteDemands(footnote.id);
|
1185
|
if (demands != null) {
|
1186
|
for (AnnotatableEntity entity : demands) {
|
1187
|
attachFootnote(state, entity, footnote);
|
1188
|
}
|
1189
|
}
|
1190
|
}
|
1191
|
|
1192
|
private void registerGivenFigure(MarkupImportState state, String id,
|
1193
|
Media figure) {
|
1194
|
state.registerFigure(id, figure);
|
1195
|
Set<AnnotatableEntity> demands = state.getFigureDemands(id);
|
1196
|
if (demands != null) {
|
1197
|
for (AnnotatableEntity entity : demands) {
|
1198
|
attachFigure(state, entity, figure);
|
1199
|
}
|
1200
|
}
|
1201
|
}
|
1202
|
|
1203
|
private void registerFootnoteDemand(MarkupImportState state,
|
1204
|
AnnotatableEntity entity, FootnoteDataHolder footnote) {
|
1205
|
FootnoteDataHolder existingFootnote = state.getFootnote(footnote.ref);
|
1206
|
if (existingFootnote != null) {
|
1207
|
attachFootnote(state, entity, existingFootnote);
|
1208
|
} else {
|
1209
|
Set<AnnotatableEntity> demands = state
|
1210
|
.getFootnoteDemands(footnote.ref);
|
1211
|
if (demands == null) {
|
1212
|
demands = new HashSet<AnnotatableEntity>();
|
1213
|
state.putFootnoteDemands(footnote.ref, demands);
|
1214
|
}
|
1215
|
demands.add(entity);
|
1216
|
}
|
1217
|
}
|
1218
|
|
1219
|
private void registerFigureDemand(MarkupImportState state,
|
1220
|
AnnotatableEntity entity, String figureRef) {
|
1221
|
Media existingFigure = state.getFigure(figureRef);
|
1222
|
if (existingFigure != null) {
|
1223
|
attachFigure(state, entity, existingFigure);
|
1224
|
} else {
|
1225
|
Set<AnnotatableEntity> demands = state.getFigureDemands(figureRef);
|
1226
|
if (demands == null) {
|
1227
|
demands = new HashSet<AnnotatableEntity>();
|
1228
|
state.putFigureDemands(figureRef, demands);
|
1229
|
}
|
1230
|
demands.add(entity);
|
1231
|
}
|
1232
|
}
|
1233
|
|
1234
|
private void attachFootnote(MarkupImportState state,
|
1235
|
AnnotatableEntity entity, FootnoteDataHolder footnote) {
|
1236
|
AnnotationType annotationType = this.getAnnotationType(state,
|
1237
|
MarkupTransformer.uuidFootnote, "Footnote",
|
1238
|
"An e-flora footnote", "fn", null);
|
1239
|
Annotation annotation = Annotation.NewInstance(footnote.string,
|
1240
|
annotationType, Language.DEFAULT());
|
1241
|
// TODO transient objects
|
1242
|
entity.addAnnotation(annotation);
|
1243
|
save(entity, state);
|
1244
|
}
|
1245
|
|
1246
|
private void attachFigure(MarkupImportState state,
|
1247
|
AnnotatableEntity entity, Media figure) {
|
1248
|
// IdentifiableEntity<?> toSave;
|
1249
|
if (entity.isInstanceOf(TextData.class)) {
|
1250
|
TextData deb = CdmBase.deproxy(entity, TextData.class);
|
1251
|
deb.addMedia(figure);
|
1252
|
// toSave = ((TaxonDescription)deb.getInDescription()).getTaxon();
|
1253
|
} else if (entity.isInstanceOf(IdentifiableMediaEntity.class)) {
|
1254
|
IdentifiableMediaEntity<?> ime = CdmBase.deproxy(entity,
|
1255
|
IdentifiableMediaEntity.class);
|
1256
|
ime.addMedia(figure);
|
1257
|
// toSave = ime;
|
1258
|
} else {
|
1259
|
String message = "Unsupported entity to attach media: %s";
|
1260
|
message = String.format(message, entity.getClass().getName());
|
1261
|
// toSave = null;
|
1262
|
}
|
1263
|
save(entity, state);
|
1264
|
}
|
1265
|
|
1266
|
private void handleFigure(MarkupImportState state, XMLEventReader reader,
|
1267
|
XMLEvent parentEvent) throws XMLStreamException {
|
1268
|
// FigureDataHolder result = new FigureDataHolder();
|
1269
|
|
1270
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
1271
|
String id = getAndRemoveAttributeValue(attributes, ID);
|
1272
|
String type = getAndRemoveAttributeValue(attributes, TYPE);
|
1273
|
checkNoAttributes(attributes, parentEvent);
|
1274
|
|
1275
|
String urlString = null;
|
1276
|
String legendString = null;
|
1277
|
String titleString = null;
|
1278
|
String numString = null;
|
1279
|
String text = null;
|
1280
|
while (reader.hasNext()) {
|
1281
|
XMLEvent next = readNoWhitespace(reader);
|
1282
|
if (isMyEndingElement(next, parentEvent)) {
|
1283
|
makeFigure(state, id, type, urlString, legendString,
|
1284
|
titleString, numString, next);
|
1285
|
return;
|
1286
|
} else if (isStartingElement(next, FIGURE_LEGEND)) {
|
1287
|
// TODO same as figurestring ?
|
1288
|
legendString = handleFootnoteString(state, reader, next);
|
1289
|
} else if (isStartingElement(next, FIGURE_TITLE)) {
|
1290
|
titleString = getCData(state, reader, next);
|
1291
|
} else if (isStartingElement(next, URL)) {
|
1292
|
String localUrl = getCData(state, reader, next);
|
1293
|
urlString = CdmUtils.Nz(state.getBaseMediaUrl()) + localUrl;
|
1294
|
} else if (isStartingElement(next, NUM)) {
|
1295
|
numString = getCData(state, reader, next);
|
1296
|
} else if (next.isCharacters()) {
|
1297
|
text += next.asCharacters().getData();
|
1298
|
} else {
|
1299
|
fireUnexpectedEvent(next, 0);
|
1300
|
}
|
1301
|
}
|
1302
|
throw new IllegalStateException("<figure> has no end tag");
|
1303
|
}
|
1304
|
|
1305
|
/**
|
1306
|
* @param state
|
1307
|
* @param id
|
1308
|
* @param type
|
1309
|
* @param urlString
|
1310
|
* @param legendString
|
1311
|
* @param titleString
|
1312
|
* @param numString
|
1313
|
* @param next
|
1314
|
*/
|
1315
|
private void makeFigure(MarkupImportState state, String id, String type,
|
1316
|
String urlString, String legendString, String titleString,
|
1317
|
String numString, XMLEvent next) {
|
1318
|
Media media = null;
|
1319
|
try {
|
1320
|
URL url = new URL(urlString);
|
1321
|
if ("lineart".equals(type)) {
|
1322
|
media = Figure.NewInstance(url.toURI(), null, null,
|
1323
|
null);
|
1324
|
} else if (type == null || "photo".equals(type)
|
1325
|
|| "signature".equals(type)
|
1326
|
|| "others".equals(type)) {
|
1327
|
media = Media.NewInstance(url.toURI(), null, null, null);
|
1328
|
} else {
|
1329
|
String message = "Unknown figure type '%s'";
|
1330
|
message = String.format(message, type);
|
1331
|
// TODO location
|
1332
|
fireWarningEvent(message, "-", 2);
|
1333
|
media = Media.NewInstance(url.toURI(), null, null, null);
|
1334
|
}
|
1335
|
// title
|
1336
|
if (StringUtils.isNotBlank(titleString)) {
|
1337
|
media.putTitle(Language.DEFAULT(), titleString);
|
1338
|
}
|
1339
|
// legend
|
1340
|
if (StringUtils.isNotBlank(legendString)) {
|
1341
|
media.addDescription(legendString, Language.DEFAULT());
|
1342
|
}
|
1343
|
if (StringUtils.isNotBlank(numString)) {
|
1344
|
// TODO use concrete source (e.g. DAPHNIPHYLLACEAE in FM
|
1345
|
// vol.13)
|
1346
|
Reference citation = state.getConfig().getSourceReference();
|
1347
|
media.addSource(numString, "num", citation, null);
|
1348
|
// TODO name used in source if available
|
1349
|
}
|
1350
|
// TODO which citation
|
1351
|
if (StringUtils.isNotBlank(id)) {
|
1352
|
media.addSource(id, null, state.getConfig()
|
1353
|
.getSourceReference(), null);
|
1354
|
} else {
|
1355
|
String message = "Figure id should never be empty or null";
|
1356
|
fireWarningEvent(message, next, 6);
|
1357
|
}
|
1358
|
// text
|
1359
|
// do nothing
|
1360
|
|
1361
|
} catch (MalformedURLException e) {
|
1362
|
String message = "Media uri has incorrect syntax: %s";
|
1363
|
message = String.format(message, urlString);
|
1364
|
fireWarningEvent(message, next, 4);
|
1365
|
} catch (URISyntaxException e) {
|
1366
|
String message = "Media uri has incorrect syntax: %s";
|
1367
|
message = String.format(message, urlString);
|
1368
|
fireWarningEvent(message, next, 4);
|
1369
|
}
|
1370
|
|
1371
|
registerGivenFigure(state, id, media);
|
1372
|
}
|
1373
|
|
1374
|
private FigureDataHolder handleFigureRef(MarkupImportState state,
|
1375
|
XMLEventReader reader, XMLEvent parentEvent)
|
1376
|
throws XMLStreamException {
|
1377
|
FigureDataHolder result = new FigureDataHolder();
|
1378
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
1379
|
result.ref = getAndRemoveAttributeValue(attributes, REF);
|
1380
|
checkNoAttributes(attributes, parentEvent);
|
1381
|
|
1382
|
// text is not handled, needed only for debugging purposes
|
1383
|
String text = "";
|
1384
|
while (reader.hasNext()) {
|
1385
|
XMLEvent next = readNoWhitespace(reader);
|
1386
|
if (isMyEndingElement(next, parentEvent)) {
|
1387
|
return result;
|
1388
|
} else if (isStartingElement(next, NUM)) {
|
1389
|
String num = getCData(state, reader, next);
|
1390
|
result.num = num; // num is not handled during import
|
1391
|
} else if (isStartingElement(next, FIGURE_PART)) {
|
1392
|
result.figurePart = getCData(state, reader, next);
|
1393
|
} else if (next.isCharacters()) {
|
1394
|
text += next.asCharacters().getData();
|
1395
|
} else {
|
1396
|
fireUnexpectedEvent(next, 0);
|
1397
|
}
|
1398
|
}
|
1399
|
throw new IllegalStateException("<figureRef> has no end tag");
|
1400
|
}
|
1401
|
|
1402
|
private FootnoteDataHolder handleFootnote(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
1403
|
FootnoteDataHolder result = new FootnoteDataHolder();
|
1404
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
1405
|
result.id = getAndRemoveAttributeValue(attributes, ID);
|
1406
|
// result.ref = getAndRemoveAttributeValue(attributes, REF);
|
1407
|
checkNoAttributes(attributes, parentEvent);
|
1408
|
|
1409
|
while (reader.hasNext()) {
|
1410
|
XMLEvent next = readNoWhitespace(reader);
|
1411
|
if (isStartingElement(next, FOOTNOTE_STRING)) {
|
1412
|
String string = handleFootnoteString(state, reader, next);
|
1413
|
result.string = string;
|
1414
|
} else if (isMyEndingElement(next, parentEvent)) {
|
1415
|
return result;
|
1416
|
} else {
|
1417
|
fireUnexpectedEvent(next, 0);
|
1418
|
}
|
1419
|
}
|
1420
|
return result;
|
1421
|
}
|
1422
|
|
1423
|
private FootnoteDataHolder handleFootnoteRef(MarkupImportState state,
|
1424
|
XMLEventReader reader, XMLEvent parentEvent)
|
1425
|
throws XMLStreamException {
|
1426
|
FootnoteDataHolder result = new FootnoteDataHolder();
|
1427
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
1428
|
result.ref = getAndRemoveAttributeValue(attributes, REF);
|
1429
|
checkNoAttributes(attributes, parentEvent);
|
1430
|
|
1431
|
// text is not handled, needed only for debugging purposes
|
1432
|
String text = "";
|
1433
|
while (reader.hasNext()) {
|
1434
|
XMLEvent next = readNoWhitespace(reader);
|
1435
|
// if (isStartingElement(next, FOOTNOTE_STRING)){
|
1436
|
// String string = handleFootnoteString(state, reader, next);
|
1437
|
// result.string = string;
|
1438
|
// }else
|
1439
|
if (isMyEndingElement(next, parentEvent)) {
|
1440
|
return result;
|
1441
|
} else if (next.isCharacters()) {
|
1442
|
text += next.asCharacters().getData();
|
1443
|
|
1444
|
} else {
|
1445
|
fireUnexpectedEvent(next, 0);
|
1446
|
}
|
1447
|
}
|
1448
|
return result;
|
1449
|
}
|
1450
|
|
1451
|
private void handleNomenclature(MarkupImportState state,
|
1452
|
XMLEventReader reader, XMLEvent parentEvent)
|
1453
|
throws XMLStreamException {
|
1454
|
checkNoAttributes(parentEvent);
|
1455
|
|
1456
|
while (reader.hasNext()) {
|
1457
|
XMLEvent next = readNoWhitespace(reader);
|
1458
|
if (isStartingElement(next, HOMOTYPES)) {
|
1459
|
handleHomotypes(state, reader, next.asStartElement());
|
1460
|
} else if (isMyEndingElement(next, parentEvent)) {
|
1461
|
return;
|
1462
|
} else {
|
1463
|
fireSchemaConflictEventExpectedStartTag(HOMOTYPES, reader);
|
1464
|
state.setUnsuccessfull();
|
1465
|
}
|
1466
|
}
|
1467
|
return;
|
1468
|
}
|
1469
|
|
1470
|
private String handleFootnoteString(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
1471
|
boolean isTextMode = true;
|
1472
|
String text = "";
|
1473
|
while (reader.hasNext()) {
|
1474
|
XMLEvent next = readNoWhitespace(reader);
|
1475
|
if (isMyEndingElement(next, parentEvent)) {
|
1476
|
return text;
|
1477
|
} else if (next.isEndElement()) {
|
1478
|
if (isEndingElement(next, FULL_NAME)) {
|
1479
|
popUnimplemented(next.asEndElement());
|
1480
|
} else if (isEndingElement(next, BR)) {
|
1481
|
isTextMode = true;
|
1482
|
} else if (isHtml(next)) {
|
1483
|
text += getXmlTag(next);
|
1484
|
} else {
|
1485
|
handleUnexpectedEndElement(next.asEndElement());
|
1486
|
}
|
1487
|
} else if (next.isStartElement()) {
|
1488
|
if (isStartingElement(next, FULL_NAME)) {
|
1489
|
handleNotYetImplementedElement(next);
|
1490
|
} else if (isStartingElement(next, GATHERING)) {
|
1491
|
text += handleInLineGathering(state, reader, next);
|
1492
|
} else if (isStartingElement(next, REFERENCES)) {
|
1493
|
text += " " + handleInLineReferences(state, reader, next)+ " ";
|
1494
|
} else if (isStartingElement(next, BR)) {
|
1495
|
text += "<br/>";
|
1496
|
isTextMode = false;
|
1497
|
} else if (isHtml(next)) {
|
1498
|
text += getXmlTag(next);
|
1499
|
} else {
|
1500
|
handleUnexpectedStartElement(next.asStartElement());
|
1501
|
}
|
1502
|
} else if (next.isCharacters()) {
|
1503
|
if (!isTextMode) {
|
1504
|
String message = "footnoteString is not in text mode";
|
1505
|
fireWarningEvent(message, next, 6);
|
1506
|
} else {
|
1507
|
text += next.asCharacters().getData().trim();
|
1508
|
// getCData(state, reader, next); does not work as we have inner tags like <references>
|
1509
|
}
|
1510
|
} else {
|
1511
|
handleUnexpectedEndElement(next.asEndElement());
|
1512
|
}
|
1513
|
}
|
1514
|
throw new IllegalStateException("<footnoteString> has no closing tag");
|
1515
|
|
1516
|
}
|
1517
|
|
1518
|
private String handleInLineGathering(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
1519
|
DerivedUnitFacade facade = DerivedUnitFacade.NewInstance(DerivedUnitType.DerivedUnit.FieldObservation);
|
1520
|
handleGathering(state, reader, parentEvent, null, facade);
|
1521
|
FieldObservation fieldObservation = facade.innerFieldObservation();
|
1522
|
String result = "<cdm:specimen uuid='%s'>%s</specimen>";
|
1523
|
result = String.format(result, fieldObservation.getUuid(), fieldObservation.getTitleCache());
|
1524
|
save(fieldObservation, state);
|
1525
|
return result;
|
1526
|
}
|
1527
|
|
1528
|
private String handleInLineReferences(MarkupImportState state,
|
1529
|
XMLEventReader reader, XMLEvent parentEvent)
|
1530
|
throws XMLStreamException {
|
1531
|
checkNoAttributes(parentEvent);
|
1532
|
|
1533
|
boolean hasReference = false;
|
1534
|
String text = "";
|
1535
|
while (reader.hasNext()) {
|
1536
|
XMLEvent next = readNoWhitespace(reader);
|
1537
|
if (isMyEndingElement(next, parentEvent)) {
|
1538
|
checkMandatoryElement(hasReference,
|
1539
|
parentEvent.asStartElement(), REFERENCE);
|
1540
|
return text;
|
1541
|
} else if (isStartingElement(next, REFERENCE)) {
|
1542
|
text += handleInLineReference(state, reader, next);
|
1543
|
hasReference = true;
|
1544
|
} else {
|
1545
|
handleUnexpectedElement(next);
|
1546
|
}
|
1547
|
}
|
1548
|
throw new IllegalStateException("<References> has no closing tag");
|
1549
|
}
|
1550
|
|
1551
|
private String handleInLineReference(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent)throws XMLStreamException {
|
1552
|
Reference<?> reference = handleReference(state, reader, parentEvent);
|
1553
|
String result = "<cdm:ref uuid='%s'>%s</ref>";
|
1554
|
result = String.format(result, reference.getUuid(), reference.getTitleCache());
|
1555
|
save(reference, state);
|
1556
|
return result;
|
1557
|
}
|
1558
|
|
1559
|
private Reference<?> handleReference(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent)throws XMLStreamException {
|
1560
|
checkNoAttributes(parentEvent);
|
1561
|
|
1562
|
boolean hasRefPart = false;
|
1563
|
Map<String, String> refMap = new HashMap<String, String>();
|
1564
|
while (reader.hasNext()) {
|
1565
|
XMLEvent next = readNoWhitespace(reader);
|
1566
|
if (isMyEndingElement(next, parentEvent)) {
|
1567
|
checkMandatoryElement(hasRefPart, parentEvent.asStartElement(),
|
1568
|
REF_PART);
|
1569
|
Reference<?> reference = createReference(state, refMap, next);
|
1570
|
return reference;
|
1571
|
} else if (isStartingElement(next, REF_PART)) {
|
1572
|
handleRefPart(state, reader, next, refMap);
|
1573
|
hasRefPart = true;
|
1574
|
} else {
|
1575
|
handleUnexpectedElement(next);
|
1576
|
}
|
1577
|
}
|
1578
|
// TODO handle missing end element
|
1579
|
throw new IllegalStateException("<Reference> has no closing tag");
|
1580
|
}
|
1581
|
|
1582
|
private void handleHomotypes(MarkupImportState state,
|
1583
|
XMLEventReader reader, StartElement parentEvent)
|
1584
|
throws XMLStreamException {
|
1585
|
checkNoAttributes(parentEvent);
|
1586
|
|
1587
|
HomotypicalGroup homotypicalGroup = null;
|
1588
|
|
1589
|
boolean hasNom = false;
|
1590
|
while (reader.hasNext()) {
|
1591
|
XMLEvent next = readNoWhitespace(reader);
|
1592
|
if (next.isEndElement()) {
|
1593
|
if (isMyEndingElement(next, parentEvent)) {
|
1594
|
checkMandatoryElement(hasNom, parentEvent, NOM);
|
1595
|
return;
|
1596
|
} else {
|
1597
|
if (isEndingElement(next, NAME_TYPE)) {
|
1598
|
state.setNameType(false);
|
1599
|
} else if (isEndingElement(next, NOTES)) {
|
1600
|
// NOT YET IMPLEMENTED
|
1601
|
popUnimplemented(next.asEndElement());
|
1602
|
} else {
|
1603
|
handleUnexpectedEndElement(next.asEndElement());
|
1604
|
}
|
1605
|
}
|
1606
|
} else if (next.isStartElement()) {
|
1607
|
if (isStartingElement(next, NOM)) {
|
1608
|
NonViralName<?> name = handleNom(state, reader, next,
|
1609
|
homotypicalGroup);
|
1610
|
homotypicalGroup = name.getHomotypicalGroup();
|
1611
|
hasNom = true;
|
1612
|
} else if (isStartingElement(next, NAME_TYPE)) {
|
1613
|
state.setNameType(true);
|
1614
|
handleNameType(state, reader, next, homotypicalGroup);
|
1615
|
} else if (isStartingElement(next, SPECIMEN_TYPE)) {
|
1616
|
handleSpecimenType(state, reader, next, homotypicalGroup);
|
1617
|
} else if (isStartingElement(next, NOTES)) {
|
1618
|
handleNotYetImplementedElement(next);
|
1619
|
} else {
|
1620
|
handleUnexpectedStartElement(next);
|
1621
|
}
|
1622
|
} else {
|
1623
|
handleUnexpectedElement(next);
|
1624
|
}
|
1625
|
}
|
1626
|
// TODO handle missing end element
|
1627
|
throw new IllegalStateException("Homotypes has no closing tag");
|
1628
|
|
1629
|
}
|
1630
|
|
1631
|
private void handleNameType(MarkupImportState state, XMLEventReader reader,
|
1632
|
XMLEvent parentEvent, HomotypicalGroup homotypicalGroup)
|
1633
|
throws XMLStreamException {
|
1634
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
1635
|
String typeStatus = getAndRemoveAttributeValue(attributes, TYPE_STATUS);
|
1636
|
checkNoAttributes(attributes, parentEvent);
|
1637
|
|
1638
|
NameTypeDesignationStatus status;
|
1639
|
try {
|
1640
|
status = NameTypeParser.parseNameTypeStatus(typeStatus);
|
1641
|
} catch (UnknownCdmTypeException e) {
|
1642
|
String message = "Type status could not be recognized: %s";
|
1643
|
message = String.format(message, typeStatus);
|
1644
|
fireWarningEvent(message, parentEvent, 4);
|
1645
|
status = null;
|
1646
|
}
|
1647
|
|
1648
|
boolean hasNom = false;
|
1649
|
while (reader.hasNext()) {
|
1650
|
XMLEvent next = readNoWhitespace(reader);
|
1651
|
if (next.isEndElement()) {
|
1652
|
if (isMyEndingElement(next, parentEvent)) {
|
1653
|
checkMandatoryElement(hasNom, parentEvent.asStartElement(),
|
1654
|
NOM);
|
1655
|
state.setNameType(false);
|
1656
|
return;
|
1657
|
} else {
|
1658
|
if (isEndingElement(next, ACCEPTED_NAME)) {
|
1659
|
// NOT YET IMPLEMENTED
|
1660
|
popUnimplemented(next.asEndElement());
|
1661
|
} else {
|
1662
|
handleUnexpectedEndElement(next.asEndElement());
|
1663
|
}
|
1664
|
}
|
1665
|
} else if (next.isStartElement()) {
|
1666
|
if (isStartingElement(next, NOM)) {
|
1667
|
// TODO should we check if the type is always a species, is
|
1668
|
// this a rule?
|
1669
|
NonViralName<?> speciesName = handleNom(state, reader,
|
1670
|
next, null);
|
1671
|
for (TaxonNameBase<?, ?> name : homotypicalGroup
|
1672
|
.getTypifiedNames()) {
|
1673
|
name.addNameTypeDesignation(speciesName, null, null,
|
1674
|
null, status, false, false, false, false);
|
1675
|
}
|
1676
|
hasNom = true;
|
1677
|
} else if (isStartingElement(next, ACCEPTED_NAME)) {
|
1678
|
handleNotYetImplementedElement(next);
|
1679
|
} else {
|
1680
|
handleUnexpectedStartElement(next);
|
1681
|
}
|
1682
|
} else {
|
1683
|
handleUnexpectedElement(next);
|
1684
|
}
|
1685
|
}
|
1686
|
// TODO handle missing end element
|
1687
|
throw new IllegalStateException("Homotypes has no closing tag");
|
1688
|
|
1689
|
}
|
1690
|
|
1691
|
private void handleSpecimenType(MarkupImportState state,
|
1692
|
XMLEventReader reader, XMLEvent parentEvent,
|
1693
|
HomotypicalGroup homotypicalGroup) throws XMLStreamException {
|
1694
|
// attributes
|
1695
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
1696
|
String typeStatus = getAndRemoveAttributeValue(attributes, TYPE_STATUS);
|
1697
|
String notSeen = getAndRemoveAttributeValue(attributes, NOT_SEEN);
|
1698
|
String unknown = getAndRemoveAttributeValue(attributes, UNKNOWN);
|
1699
|
String notFound = getAndRemoveAttributeValue(attributes, NOT_FOUND);
|
1700
|
String destroyed = getAndRemoveAttributeValue(attributes, DESTROYED);
|
1701
|
String lost = getAndRemoveAttributeValue(attributes, LOST);
|
1702
|
checkNoAttributes(attributes, parentEvent);
|
1703
|
if (StringUtils.isNotEmpty(typeStatus)) {
|
1704
|
// TODO
|
1705
|
// currently not needed
|
1706
|
} else if (StringUtils.isNotEmpty(notSeen)) {
|
1707
|
handleNotYetImplementedAttribute(attributes, NOT_SEEN);
|
1708
|
} else if (StringUtils.isNotEmpty(unknown)) {
|
1709
|
handleNotYetImplementedAttribute(attributes, UNKNOWN);
|
1710
|
} else if (StringUtils.isNotEmpty(notFound)) {
|
1711
|
handleNotYetImplementedAttribute(attributes, NOT_FOUND);
|
1712
|
} else if (StringUtils.isNotEmpty(destroyed)) {
|
1713
|
handleNotYetImplementedAttribute(attributes, DESTROYED);
|
1714
|
} else if (StringUtils.isNotEmpty(lost)) {
|
1715
|
handleNotYetImplementedAttribute(attributes, LOST);
|
1716
|
}
|
1717
|
|
1718
|
NonViralName<?> firstName = null;
|
1719
|
Set<TaxonNameBase> names = homotypicalGroup.getTypifiedNames();
|
1720
|
if (names.isEmpty()) {
|
1721
|
String message = "There is no name in a homotypical group. Can't create the specimen type";
|
1722
|
fireWarningEvent(message, parentEvent, 8);
|
1723
|
} else {
|
1724
|
firstName = CdmBase.deproxy(names.iterator().next(),
|
1725
|
NonViralName.class);
|
1726
|
}
|
1727
|
|
1728
|
DerivedUnitFacade facade = DerivedUnitFacade
|
1729
|
.NewInstance(DerivedUnitType.Specimen);
|
1730
|
String text = "";
|
1731
|
// elements
|
1732
|
while (reader.hasNext()) {
|
1733
|
XMLEvent next = readNoWhitespace(reader);
|
1734
|
if (next.isEndElement()) {
|
1735
|
if (isMyEndingElement(next, parentEvent)) {
|
1736
|
makeSpecimenType(state, facade, text, firstName,
|
1737
|
parentEvent);
|
1738
|
return;
|
1739
|
} else {
|
1740
|
if (isEndingElement(next, FULL_TYPE)) {
|
1741
|
// NOT YET IMPLEMENTED
|
1742
|
popUnimplemented(next.asEndElement());
|
1743
|
} else if (isEndingElement(next, TYPE_STATUS)) {
|
1744
|
// NOT YET IMPLEMENTED
|
1745
|
popUnimplemented(next.asEndElement());
|
1746
|
} else if (isEndingElement(next, ORIGINAL_DETERMINATION)) {
|
1747
|
// NOT YET IMPLEMENTED
|
1748
|
popUnimplemented(next.asEndElement());
|
1749
|
} else if (isEndingElement(next, SPECIMEN_TYPE)) {
|
1750
|
// NOT YET IMPLEMENTED
|
1751
|
popUnimplemented(next.asEndElement());
|
1752
|
} else if (isEndingElement(next, CITATION)) {
|
1753
|
// NOT YET IMPLEMENTED
|
1754
|
popUnimplemented(next.asEndElement());
|
1755
|
} else if (isEndingElement(next, NOTES)) {
|
1756
|
// NOT YET IMPLEMENTED
|
1757
|
popUnimplemented(next.asEndElement());
|
1758
|
} else if (isEndingElement(next, ANNOTATION)) {
|
1759
|
// NOT YET IMPLEMENTED
|
1760
|
popUnimplemented(next.asEndElement());
|
1761
|
} else {
|
1762
|
handleUnexpectedEndElement(next.asEndElement());
|
1763
|
}
|
1764
|
}
|
1765
|
} else if (next.isStartElement()) {
|
1766
|
if (isStartingElement(next, FULL_TYPE)) {
|
1767
|
handleNotYetImplementedElement(next);
|
1768
|
// homotypicalGroup = handleNom(state, reader, next, taxon,
|
1769
|
// homotypicalGroup);
|
1770
|
} else if (isStartingElement(next, TYPE_STATUS)) {
|
1771
|
handleNotYetImplementedElement(next);
|
1772
|
} else if (isStartingElement(next, GATHERING)) {
|
1773
|
handleGathering(state, reader, next, homotypicalGroup, facade);
|
1774
|
} else if (isStartingElement(next, ORIGINAL_DETERMINATION)) {
|
1775
|
handleNotYetImplementedElement(next);
|
1776
|
} else if (isStartingElement(next, SPECIMEN_TYPE)) {
|
1777
|
handleNotYetImplementedElement(next);
|
1778
|
} else if (isStartingElement(next, NOTES)) {
|
1779
|
handleNotYetImplementedElement(next);
|
1780
|
} else if (isStartingElement(next, ANNOTATION)) {
|
1781
|
handleNotYetImplementedElement(next);
|
1782
|
} else {
|
1783
|
handleUnexpectedStartElement(next);
|
1784
|
}
|
1785
|
} else if (next.isCharacters()) {
|
1786
|
text += next.asCharacters().getData();
|
1787
|
} else {
|
1788
|
handleUnexpectedElement(next);
|
1789
|
}
|
1790
|
}
|
1791
|
// TODO handle missing end element
|
1792
|
throw new IllegalStateException("Specimen type has no closing tag");
|
1793
|
}
|
1794
|
|
1795
|
private void makeSpecimenType(MarkupImportState state,
|
1796
|
DerivedUnitFacade facade, String text, NonViralName name,
|
1797
|
XMLEvent parentEvent) {
|
1798
|
text = text.trim();
|
1799
|
// remove brackets
|
1800
|
if (text.matches("^\\(.*\\)\\.?$")) {
|
1801
|
text = text.replaceAll("\\.", "");
|
1802
|
text = text.substring(1, text.length() - 1);
|
1803
|
}
|
1804
|
String[] split = text.split("[;,]");
|
1805
|
for (String str : split) {
|
1806
|
str = str.trim();
|
1807
|
boolean addToAllNamesInGroup = true;
|
1808
|
TypeInfo typeInfo = makeSpecimenTypeTypeInfo(str, parentEvent);
|
1809
|
SpecimenTypeDesignationStatus typeStatus = typeInfo.status;
|
1810
|
Collection collection = createCollection(typeInfo.collectionString);
|
1811
|
|
1812
|
// TODO improve cache strategy handling
|
1813
|
DerivedUnitBase typeSpecimen = facade.addDuplicate(collection,
|
1814
|
null, null, null, null);
|
1815
|
typeSpecimen.setCacheStrategy(new DerivedUnitFacadeCacheStrategy());
|
1816
|
name.addSpecimenTypeDesignation((Specimen) typeSpecimen, typeStatus, null, null, null, false, addToAllNamesInGroup);
|
1817
|
}
|
1818
|
}
|
1819
|
|
1820
|
private Collection createCollection(String code) {
|
1821
|
// TODO deduplicate
|
1822
|
// TODO code <-> name
|
1823
|
Collection result = Collection.NewInstance();
|
1824
|
result.setCode(code);
|
1825
|
return result;
|
1826
|
}
|
1827
|
|
1828
|
private TypeInfo makeSpecimenTypeTypeInfo(String originalString,
|
1829
|
XMLEvent event) {
|
1830
|
TypeInfo result = new TypeInfo();
|
1831
|
String[] split = originalString.split("\\s+");
|
1832
|
for (String str : split) {
|
1833
|
if (str.matches(SpecimenTypeParser.typeTypePattern)) {
|
1834
|
SpecimenTypeDesignationStatus status;
|
1835
|
try {
|
1836
|
status = SpecimenTypeParser.parseSpecimenTypeStatus(str);
|
1837
|
} catch (UnknownCdmTypeException e) {
|
1838
|
String message = "Specimen type status '%s' not recognized by parser";
|
1839
|
message = String.format(message, str);
|
1840
|
fireWarningEvent(message, event, 4);
|
1841
|
status = null;
|
1842
|
}
|
1843
|
result.status = status;
|
1844
|
} else if (str.matches(SpecimenTypeParser.collectionPattern)) {
|
1845
|
result.collectionString = str;
|
1846
|
} else {
|
1847
|
String message = "Type part '%s' could not be recognized";
|
1848
|
message = String.format(message, str);
|
1849
|
fireWarningEvent(message, event, 2);
|
1850
|
}
|
1851
|
}
|
1852
|
|
1853
|
return result;
|
1854
|
}
|
1855
|
|
1856
|
|
1857
|
private void handleGathering(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, HomotypicalGroup homotypicalGroup, DerivedUnitFacade facade) throws XMLStreamException {
|
1858
|
checkNoAttributes(parentEvent);
|
1859
|
boolean hasCollector = false;
|
1860
|
boolean hasFieldNum = false;
|
1861
|
|
1862
|
// elements
|
1863
|
while (reader.hasNext()) {
|
1864
|
XMLEvent next = readNoWhitespace(reader);
|
1865
|
if (next.isEndElement()) {
|
1866
|
if (isMyEndingElement(next, parentEvent)) {
|
1867
|
checkMandatoryElement(hasCollector,
|
1868
|
parentEvent.asStartElement(), COLLECTOR);
|
1869
|
checkMandatoryElement(hasFieldNum,
|
1870
|
parentEvent.asStartElement(), FIELD_NUM);
|
1871
|
return;
|
1872
|
} else {
|
1873
|
if (isEndingElement(next, ALTERNATIVE_COLLECTOR)) {
|
1874
|
// NOT YET IMPLEMENTED
|
1875
|
popUnimplemented(next.asEndElement());
|
1876
|
} else if (isEndingElement(next, ALTERNATIVE_FIELD_NUM)) {
|
1877
|
// NOT YET IMPLEMENTED
|
1878
|
popUnimplemented(next.asEndElement());
|
1879
|
} else if (isEndingElement(next, COLLECTION_TYPE_STATUS)) {
|
1880
|
// NOT YET IMPLEMENTED
|
1881
|
popUnimplemented(next.asEndElement());
|
1882
|
} else if (isEndingElement(next,
|
1883
|
ALTERNATIVE_COLLECTION_TYPE_STATUS)) {
|
1884
|
// NOT YET IMPLEMENTED
|
1885
|
popUnimplemented(next.asEndElement());
|
1886
|
} else if (isEndingElement(next, SUB_COLLECTION)) {
|
1887
|
// NOT YET IMPLEMENTED
|
1888
|
popUnimplemented(next.asEndElement());
|
1889
|
} else if (isEndingElement(next, DATES)) {
|
1890
|
// NOT YET IMPLEMENTED
|
1891
|
popUnimplemented(next.asEndElement());
|
1892
|
} else if (isEndingElement(next, NOTES)) {
|
1893
|
// NOT YET IMPLEMENTED
|
1894
|
popUnimplemented(next.asEndElement());
|
1895
|
} else {
|
1896
|
handleUnexpectedEndElement(next.asEndElement());
|
1897
|
}
|
1898
|
}
|
1899
|
} else if (next.isStartElement()) {
|
1900
|
if (isStartingElement(next, COLLECTOR)) {
|
1901
|
hasCollector = true;
|
1902
|
String collectorStr = getCData(state, reader, next);
|
1903
|
AgentBase<?> collector = createCollector(collectorStr);
|
1904
|
facade.setCollector(collector);
|
1905
|
} else if (isStartingElement(next, ALTERNATIVE_COLLECTOR)) {
|
1906
|
handleNotYetImplementedElement(next);
|
1907
|
} else if (isStartingElement(next, FIELD_NUM)) {
|
1908
|
hasFieldNum = true;
|
1909
|
String fieldNumStr = getCData(state, reader, next);
|
1910
|
facade.setFieldNumber(fieldNumStr);
|
1911
|
} else if (isStartingElement(next, ALTERNATIVE_FIELD_NUM)) {
|
1912
|
handleNotYetImplementedElement(next);
|
1913
|
} else if (isStartingElement(next, COLLECTION_TYPE_STATUS)) {
|
1914
|
handleNotYetImplementedElement(next);
|
1915
|
} else if (isStartingElement(next,
|
1916
|
ALTERNATIVE_COLLECTION_TYPE_STATUS)) {
|
1917
|
handleNotYetImplementedElement(next);
|
1918
|
} else if (isStartingElement(next, SUB_COLLECTION)) {
|
1919
|
handleNotYetImplementedElement(next);
|
1920
|
} else if (isStartingElement(next, LOCALITY)) {
|
1921
|
handleLocality(state, reader, next, facade);
|
1922
|
} else if (isStartingElement(next, DATES)) {
|
1923
|
handleNotYetImplementedElement(next);
|
1924
|
} else if (isStartingElement(next, NOTES)) {
|
1925
|
handleNotYetImplementedElement(next);
|
1926
|
} else {
|
1927
|
handleUnexpectedStartElement(next);
|
1928
|
}
|
1929
|
} else {
|
1930
|
handleUnexpectedElement(next);
|
1931
|
}
|
1932
|
}
|
1933
|
// TODO handle missing end element
|
1934
|
throw new IllegalStateException("Collection has no closing tag");
|
1935
|
|
1936
|
}
|
1937
|
|
1938
|
private void handleLocality(MarkupImportState state, XMLEventReader reader,XMLEvent parentEvent, DerivedUnitFacade facade)throws XMLStreamException {
|
1939
|
String classValue = getClassOnlyAttribute(parentEvent);
|
1940
|
boolean isLocality = false;
|
1941
|
NamedAreaLevel areaLevel = null;
|
1942
|
if ("locality".equalsIgnoreCase(classValue)) {
|
1943
|
isLocality = true;
|
1944
|
} else {
|
1945
|
areaLevel = makeNamedAreaLevel(state, classValue, parentEvent);
|
1946
|
}
|
1947
|
|
1948
|
String text = "";
|
1949
|
// elements
|
1950
|
while (reader.hasNext()) {
|
1951
|
XMLEvent next = readNoWhitespace(reader);
|
1952
|
if (next.isEndElement()) {
|
1953
|
if (StringUtils.isNotBlank(text)) {
|
1954
|
if (isMyEndingElement(next, parentEvent)) {
|
1955
|
if (isLocality) {
|
1956
|
facade.setLocality(text);
|
1957
|
} else {
|
1958
|
NamedArea area = createArea(text, areaLevel, state);
|
1959
|
facade.addCollectingArea(area);
|
1960
|
}
|
1961
|
}
|
1962
|
// TODO
|
1963
|
return;
|
1964
|
} else {
|
1965
|
if (isEndingElement(next, ALTITUDE)) {
|
1966
|
// NOT YET IMPLEMENTED
|
1967
|
popUnimplemented(next.asEndElement());
|
1968
|
} else if (isEndingElement(next, COORDINATES)) {
|
1969
|
// NOT YET IMPLEMENTED
|
1970
|
popUnimplemented(next.asEndElement());
|
1971
|
} else if (isEndingElement(next, ANNOTATION)) {
|
1972
|
// NOT YET IMPLEMENTED
|
1973
|
popUnimplemented(next.asEndElement());
|
1974
|
} else {
|
1975
|
handleUnexpectedEndElement(next.asEndElement());
|
1976
|
}
|
1977
|
}
|
1978
|
} else if (next.isStartElement()) {
|
1979
|
if (isStartingElement(next, ALTITUDE)) {
|
1980
|
handleNotYetImplementedElement(next);
|
1981
|
// homotypicalGroup = handleNom(state, reader, next, taxon,
|
1982
|
// homotypicalGroup);
|
1983
|
} else if (isStartingElement(next, COORDINATES)) {
|
1984
|
handleNotYetImplementedElement(next);
|
1985
|
} else if (isStartingElement(next, ANNOTATION)) {
|
1986
|
handleNotYetImplementedElement(next);
|
1987
|
} else {
|
1988
|
handleUnexpectedStartElement(next);
|
1989
|
}
|
1990
|
} else if (next.isCharacters()) {
|
1991
|
text += next.asCharacters().getData();
|
1992
|
} else {
|
1993
|
handleUnexpectedElement(next);
|
1994
|
}
|
1995
|
}
|
1996
|
// TODO handle missing end element
|
1997
|
throw new IllegalStateException("Specimen type has no closing tag"); // TODO
|
1998
|
// Auto-generated
|
1999
|
// method
|
2000
|
// stub
|
2001
|
|
2002
|
}
|
2003
|
|
2004
|
private NamedArea createArea(String text, NamedAreaLevel areaLevel, MarkupImportState state) {
|
2005
|
NamedArea area = NamedArea.NewInstance(text, text, null);
|
2006
|
area.setLevel(areaLevel);
|
2007
|
save(area, state);
|
2008
|
return area;
|
2009
|
}
|
2010
|
|
2011
|
private AgentBase<?> createCollector(String collectorStr) {
|
2012
|
return createAuthor(collectorStr);
|
2013
|
}
|
2014
|
|
2015
|
private String getCData(MarkupImportState state, XMLEventReader reader, XMLEvent next) throws XMLStreamException {
|
2016
|
return getCData(state, reader, next, true);
|
2017
|
}
|
2018
|
|
2019
|
/**
|
2020
|
* Reads character data. Any element other than character data or the ending
|
2021
|
* tag will fire an unexpected element event.
|
2022
|
*
|
2023
|
* @param state
|
2024
|
* @param reader
|
2025
|
* @param next
|
2026
|
* @return
|
2027
|
* @throws XMLStreamException
|
2028
|
*/
|
2029
|
private String getCData(MarkupImportState state, XMLEventReader reader, XMLEvent next,boolean checkAttributes) throws XMLStreamException {
|
2030
|
if (checkAttributes){
|
2031
|
checkNoAttributes(next);
|
2032
|
}
|
2033
|
|
2034
|
String text = "";
|
2035
|
while (reader.hasNext()) {
|
2036
|
XMLEvent myNext = readNoWhitespace(reader);
|
2037
|
if (isMyEndingElement(myNext, next)) {
|
2038
|
return text;
|
2039
|
} else if (myNext.isCharacters()) {
|
2040
|
text += myNext.asCharacters().getData();
|
2041
|
} else {
|
2042
|
handleUnexpectedElement(myNext);
|
2043
|
}
|
2044
|
}
|
2045
|
throw new IllegalStateException("Event has no closing tag");
|
2046
|
|
2047
|
}
|
2048
|
|
2049
|
/**
|
2050
|
* Creates the name defined by a nom tag. Adds it to the given homotypical
|
2051
|
* group (if not null).
|
2052
|
*
|
2053
|
* @param state
|
2054
|
* @param reader
|
2055
|
* @param parentEvent
|
2056
|
* @param homotypicalGroup
|
2057
|
* @return
|
2058
|
* @throws XMLStreamException
|
2059
|
*/
|
2060
|
private NonViralName<?> handleNom(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent,
|
2061
|
HomotypicalGroup homotypicalGroup) throws XMLStreamException {
|
2062
|
boolean isSynonym = false;
|
2063
|
boolean isNameType = state.isNameType();
|
2064
|
// attributes
|
2065
|
String classValue = getClassOnlyAttribute(parentEvent);
|
2066
|
NonViralName<?> name;
|
2067
|
if (!isNameType && ACCEPTED.equalsIgnoreCase(classValue)) {
|
2068
|
isSynonym = false;
|
2069
|
name = createName(state, homotypicalGroup, isSynonym);
|
2070
|
} else if (!isNameType && SYNONYM.equalsIgnoreCase(classValue)) {
|
2071
|
isSynonym = true;
|
2072
|
name = createName(state, homotypicalGroup, isSynonym);
|
2073
|
} else if (isNameType && NAME_TYPE.equalsIgnoreCase(classValue)) {
|
2074
|
// TODO do we need to define the rank here?
|
2075
|
name = createNameByCode(state, null);
|
2076
|
} else {
|
2077
|
fireUnexpectedAttributeValue(parentEvent, CLASS, classValue);
|
2078
|
name = createNameByCode(state, null);
|
2079
|
}
|
2080
|
|
2081
|
Map<String, String> nameMap = new HashMap<String, String>();
|
2082
|
|
2083
|
while (reader.hasNext()) {
|
2084
|
XMLEvent next = readNoWhitespace(reader);
|
2085
|
if (next.isEndElement()) {
|
2086
|
if (isMyEndingElement(next, parentEvent)) {
|
2087
|
// fill the name with all data gathered
|
2088
|
fillName(state, nameMap, name, next);
|
2089
|
return name;
|
2090
|
} else {
|
2091
|
if (isEndingElement(next, FULL_NAME)) {
|
2092
|
// NOT YET IMPLEMENTED
|
2093
|
popUnimplemented(next.asEndElement());
|
2094
|
} else if (isEndingElement(next, NUM)) {
|
2095
|
// NOT YET IMPLEMENTED
|
2096
|
popUnimplemented(next.asEndElement());
|
2097
|
} else if (isEndingElement(next, HOMONYM)) {
|
2098
|
// NOT YET IMPLEMENTED
|
2099
|
popUnimplemented(next.asEndElement());
|
2100
|
} else if (isEndingElement(next, NOTES)) {
|
2101
|
// NOT YET IMPLEMENTED
|
2102
|
popUnimplemented(next.asEndElement());
|
2103
|
} else if (isEndingElement(next, ANNOTATION)) {
|
2104
|
// NOT YET IMPLEMENTED
|
2105
|
popUnimplemented(next.asEndElement());
|
2106
|
} else {
|
2107
|
handleUnexpectedEndElement(next.asEndElement());
|
2108
|
}
|
2109
|
}
|
2110
|
} else if (next.isStartElement()) {
|
2111
|
if (isStartingElement(next, FULL_NAME)) {
|
2112
|
handleNotYetImplementedElement(next);
|
2113
|
// homotypicalGroup = handleNom(state, reader, next, taxon,
|
2114
|
// homotypicalGroup);
|
2115
|
} else if (isStartingElement(next, NUM)) {
|
2116
|
handleNotYetImplementedElement(next);
|
2117
|
} else if (isStartingElement(next, NAME)) {
|
2118
|
handleName(state, reader, next, nameMap);
|
2119
|
} else if (isStartingElement(next, CITATION)) {
|
2120
|
handleCitation(state, reader, next, name);
|
2121
|
} else if (isStartingElement(next, HOMONYM)) {
|
2122
|
handleNotYetImplementedElement(next);
|
2123
|
} else if (isStartingElement(next, NOTES)) {
|
2124
|
handleNotYetImplementedElement(next);
|
2125
|
} else if (isStartingElement(next, ANNOTATION)) {
|
2126
|
handleNotYetImplementedElement(next);
|
2127
|
} else {
|
2128
|
handleUnexpectedStartElement(next);
|
2129
|
}
|
2130
|
} else {
|
2131
|
handleUnexpectedElement(next);
|
2132
|
}
|
2133
|
}
|
2134
|
// TODO handle missing end element
|
2135
|
throw new IllegalStateException("Nom has no closing tag");
|
2136
|
|
2137
|
}
|
2138
|
|
2139
|
private void fillName(MarkupImportState state, Map<String, String> nameMap,
|
2140
|
NonViralName name, XMLEvent event) {
|
2141
|
|
2142
|
// Ranks: family, subfamily, tribus, genus, subgenus, section,
|
2143
|
// subsection, species, subspecies, variety, subvariety, forma
|
2144
|
// infrank, paraut, author, infrparaut, infraut, status, notes
|
2145
|
|
2146
|
String infrank = getAndRemoveMapKey(nameMap, INFRANK);
|
2147
|
String authorStr = getAndRemoveMapKey(nameMap, AUTHOR);
|
2148
|
String paraut = getAndRemoveMapKey(nameMap, PARAUT);
|
2149
|
|
2150
|
String infrParAut = getAndRemoveMapKey(nameMap, INFRPARAUT);
|
2151
|
String infrAut = getAndRemoveMapKey(nameMap, INFRAUT);
|
2152
|
|
2153
|
String statusStr = getAndRemoveMapKey(nameMap, STATUS);
|
2154
|
String notes = getAndRemoveMapKey(nameMap, NOTES);
|
2155
|
|
2156
|
makeRankDecision(state, nameMap, name, event, infrank);
|
2157
|
|
2158
|
// test consistency of rank and authors
|
2159
|
testRankAuthorConsistency(name, event, authorStr, paraut, infrParAut,infrAut);
|
2160
|
|
2161
|
// authors
|
2162
|
makeNomenclaturalAuthors(name, event, authorStr, paraut, infrParAut,infrAut);
|
2163
|
|
2164
|
// status
|
2165
|
// TODO handle pro parte, pro syn. etc.
|
2166
|
if (StringUtils.isNotBlank(statusStr)) {
|
2167
|
String proPartePattern = "(pro parte|p.p.)";
|
2168
|
if (statusStr.matches(proPartePattern)) {
|
2169
|
state.setProParte(true);
|
2170
|
}
|
2171
|
try {
|
2172
|
// TODO handle trim earlier
|
2173
|
statusStr = statusStr.trim();
|
2174
|
NomenclaturalStatusType nomStatusType = NomenclaturalStatusType
|
2175
|
.getNomenclaturalStatusTypeByAbbreviation(statusStr);
|
2176
|
name.addStatus(NomenclaturalStatus.NewInstance(nomStatusType));
|
2177
|
} catch (UnknownCdmTypeException e) {
|
2178
|
String message = "Status '%s' could not be recognized";
|
2179
|
message = String.format(message, statusStr);
|
2180
|
fireWarningEvent(message, event, 4);
|
2181
|
}
|
2182
|
}
|
2183
|
|
2184
|
// notes
|
2185
|
if (StringUtils.isNotBlank(notes)) {
|
2186
|
handleNotYetImplementedAttributeValue(event, CLASS, NOTES);
|
2187
|
}
|
2188
|
|
2189
|
return;
|
2190
|
}
|
2191
|
|
2192
|
/**
|
2193
|
* @param state
|
2194
|
* @param nameMap
|
2195
|
* @param name
|
2196
|
* @param event
|
2197
|
* @param infrankStr
|
2198
|
*/
|
2199
|
private void makeRankDecision(MarkupImportState state,
|
2200
|
Map<String, String> nameMap, NonViralName<?> name, XMLEvent event,
|
2201
|
String infrankStr) {
|
2202
|
// TODO ranks
|
2203
|
for (String key : nameMap.keySet()) {
|
2204
|
Rank rank = makeRank(state, key, false);
|
2205
|
if (rank == null) {
|
2206
|
handleNotYetImplementedAttributeValue(event, CLASS, key);
|
2207
|
} else {
|
2208
|
if (name.getRank() == null || rank.isLower(name.getRank())) {
|
2209
|
name.setRank(rank);
|
2210
|
}
|
2211
|
String value = nameMap.get(key);
|
2212
|
if (rank.isSupraGeneric() || rank.isGenus()) {
|
2213
|
name.setGenusOrUninomial(value);
|
2214
|
} else if (rank.isInfraGeneric()) {
|
2215
|
name.setInfraGenericEpithet(value);
|
2216
|
} else if (rank.isSpecies()) {
|
2217
|
name.setSpecificEpithet(value);
|
2218
|
} else if (rank.isInfraSpecific()) {
|
2219
|
name.setInfraSpecificEpithet(value);
|
2220
|
} else {
|
2221
|
String message = "Invalid rank '%s'. Can't decide which epithet to fill with '%s'";
|
2222
|
message = String.format(message, rank.getTitleCache(),value);
|
2223
|
fireWarningEvent(message, event, 4);
|
2224
|
}
|
2225
|
}
|
2226
|
|
2227
|
}
|
2228
|
// handle given infrank marker
|
2229
|
if (StringUtils.isNotBlank(infrankStr)) {
|
2230
|
Rank infRank = makeRank(state, infrankStr, true);
|
2231
|
|
2232
|
if (infRank == null) {
|
2233
|
String message = "Infrank '%s' rank not recognized";
|
2234
|
message = String.format(message, infrankStr);
|
2235
|
fireWarningEvent(message, event, 4);
|
2236
|
} else {
|
2237
|
if (name.getRank() == null) {
|
2238
|
name.setRank(infRank);
|
2239
|
} else if (infRank.isLower(name.getRank())) {
|
2240
|
String message = "InfRank '%s' is lower than existing rank ";
|
2241
|
message = String.format(message, infrankStr);
|
2242
|
fireWarningEvent(message, event, 2);
|
2243
|
name.setRank(infRank);
|
2244
|
} else if (infRank.equals(name.getRank())) {
|
2245
|
// nothing
|
2246
|
} else {
|
2247
|
String message = "InfRank '%s' is higher than existing rank ";
|
2248
|
message = String.format(message, infrankStr);
|
2249
|
fireWarningEvent(message, event, 2);
|
2250
|
}
|
2251
|
}
|
2252
|
}
|
2253
|
}
|
2254
|
|
2255
|
/**
|
2256
|
* @param name
|
2257
|
* @param event
|
2258
|
* @param authorStr
|
2259
|
* @param paraut
|
2260
|
* @param infrParAut
|
2261
|
* @param infrAut
|
2262
|
*/
|
2263
|
private void makeNomenclaturalAuthors(NonViralName name, XMLEvent event,
|
2264
|
String authorStr, String paraut, String infrParAut, String infrAut) {
|
2265
|
if (name.getRank() != null && name.getRank().isInfraSpecific()) {
|
2266
|
if (StringUtils.isNotBlank(infrAut)) {
|
2267
|
INomenclaturalAuthor[] authorAndEx = authorAndEx(infrAut, event);
|
2268
|
name.setCombinationAuthorTeam(authorAndEx[0]);
|
2269
|
name.setExCombinationAuthorTeam(authorAndEx[1]);
|
2270
|
}
|
2271
|
if (StringUtils.isNotBlank(infrParAut)) {
|
2272
|
INomenclaturalAuthor[] authorAndEx = authorAndEx(infrParAut, event);
|
2273
|
name.setBasionymAuthorTeam(authorAndEx[0]);
|
2274
|
name.setExBasionymAuthorTeam(authorAndEx[1]);
|
2275
|
}
|
2276
|
} else {
|
2277
|
if (name.getRank() == null){
|
2278
|
String message = "No rank defined. Check correct usage of authors!";
|
2279
|
fireWarningEvent(message, event, 4);
|
2280
|
if (isNotBlank(infrParAut) || isNotBlank(infrAut)){
|
2281
|
authorStr = infrAut;
|
2282
|
paraut = infrParAut;
|
2283
|
}
|
2284
|
}
|
2285
|
if (StringUtils.isNotBlank(authorStr)) {
|
2286
|
INomenclaturalAuthor[] authorAndEx = authorAndEx(authorStr, event);
|
2287
|
name.setCombinationAuthorTeam(authorAndEx[0]);
|
2288
|
name.setExCombinationAuthorTeam(authorAndEx[1]);
|
2289
|
}
|
2290
|
if (StringUtils.isNotBlank(paraut)) {
|
2291
|
INomenclaturalAuthor[] authorAndEx = authorAndEx(paraut, event);
|
2292
|
name.setBasionymAuthorTeam(authorAndEx[0]);
|
2293
|
name.setExBasionymAuthorTeam(authorAndEx[1]);
|
2294
|
}
|
2295
|
}
|
2296
|
}
|
2297
|
|
2298
|
private TeamOrPersonBase[] authorAndEx(String authorAndEx, XMLEvent xmlEvent) {
|
2299
|
authorAndEx = authorAndEx.trim();
|
2300
|
TeamOrPersonBase[] result = new TeamOrPersonBase[2];
|
2301
|
|
2302
|
String[] split = authorAndEx.split("\\sex\\s");
|
2303
|
if (split.length > 2) {
|
2304
|
String message = "There is more then 1 ' ex ' in author string. Can't separate author and ex-author";
|
2305
|
fireWarningEvent(message, xmlEvent, 4);
|
2306
|
result[0] = createAuthor(authorAndEx);
|
2307
|
} else if (split.length == 2) {
|
2308
|
result[0] = createAuthor(split[1]);
|
2309
|
result[1] = createAuthor(split[0]);
|
2310
|
} else {
|
2311
|
result[0] = createAuthor(split[0]);
|
2312
|
}
|
2313
|
return result;
|
2314
|
}
|
2315
|
|
2316
|
/**
|
2317
|
* Tests if the names rank is consistent with the given author strings.
|
2318
|
* @param name
|
2319
|
* @param event
|
2320
|
* @param authorStr
|
2321
|
* @param paraut
|
2322
|
* @param infrParAut
|
2323
|
* @param infrAut
|
2324
|
*/
|
2325
|
private void testRankAuthorConsistency(NonViralName name, XMLEvent event,
|
2326
|
String authorStr, String paraut, String infrParAut, String infrAut) {
|
2327
|
if (name.getRank() == null){
|
2328
|
return;
|
2329
|
}
|
2330
|
if (name.getRank().isInfraSpecific()) {
|
2331
|
if (StringUtils.isBlank(infrParAut)
|
2332
|
&& StringUtils.isNotBlank(infrAut)
|
2333
|
&& (StringUtils.isNotBlank(paraut) || StringUtils.isNotBlank(authorStr))) {
|
2334
|
String message = "Rank is infraspecicific but has only specific or higher author(s)";
|
2335
|
fireWarningEvent(message, event, 4);
|
2336
|
}
|
2337
|
} else {
|
2338
|
// is not infraspecific
|
2339
|
if (StringUtils.isNotBlank(infrParAut) || StringUtils.isNotBlank(infrAut)) {
|
2340
|
String message = "Rank is not infraspecicific but name has infra author(s)";
|
2341
|
fireWarningEvent(message, event, 4);
|
2342
|
}
|
2343
|
}
|
2344
|
}
|
2345
|
|
2346
|
/**
|
2347
|
* Returns the (empty) name with the correct homotypical group depending on
|
2348
|
* the taxon status. Throws NPE if no currentTaxon is set in state.
|
2349
|
*
|
2350
|
* @param state
|
2351
|
* @param homotypicalGroup
|
2352
|
* @param isSynonym
|
2353
|
* @return
|
2354
|
*/
|
2355
|
private NonViralName<?> createName(MarkupImportState state,
|
2356
|
HomotypicalGroup homotypicalGroup, boolean isSynonym) {
|
2357
|
NonViralName<?> name;
|
2358
|
Taxon taxon = state.getCurrentTaxon();
|
2359
|
if (isSynonym) {
|
2360
|
Rank defaultRank = Rank.SPECIES(); // can be any
|
2361
|
name = createNameByCode(state, defaultRank);
|
2362
|
if (homotypicalGroup != null) {
|
2363
|
name.setHomotypicalGroup(homotypicalGroup);
|
2364
|
}
|
2365
|
SynonymRelationshipType synonymType = SynonymRelationshipType
|
2366
|
.HETEROTYPIC_SYNONYM_OF();
|
2367
|
if (taxon.getHomotypicGroup().equals(homotypicalGroup)) {
|
2368
|
synonymType = SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF();
|
2369
|
}
|
2370
|
taxon.addSynonymName(name, synonymType);
|
2371
|
} else {
|
2372
|
name = CdmBase.deproxy(taxon.getName(), NonViralName.class);
|
2373
|
}
|
2374
|
return name;
|
2375
|
}
|
2376
|
|
2377
|
private void handleName(MarkupImportState state, XMLEventReader reader,
|
2378
|
XMLEvent parentEvent, Map<String, String> nameMap)
|
2379
|
throws XMLStreamException {
|
2380
|
String classValue = getClassOnlyAttribute(parentEvent);
|
2381
|
|
2382
|
String text = "";
|
2383
|
while (reader.hasNext()) {
|
2384
|
XMLEvent next = readNoWhitespace(reader);
|
2385
|
if (isMyEndingElement(next, parentEvent)) {
|
2386
|
nameMap.put(classValue, text);
|
2387
|
return;
|
2388
|
} else if (next.isStartElement()) {
|
2389
|
if (isStartingElement(next, ANNOTATION)) {
|
2390
|
handleNotYetImplementedElement(next);
|
2391
|
} else {
|
2392
|
handleUnexpectedStartElement(next.asStartElement());
|
2393
|
}
|
2394
|
} else if (next.isCharacters()) {
|
2395
|
text += next.asCharacters().getData();
|
2396
|
} else {
|
2397
|
handleUnexpectedEndElement(next.asEndElement());
|
2398
|
}
|
2399
|
}
|
2400
|
throw new IllegalStateException("name has no closing tag");
|
2401
|
|
2402
|
}
|
2403
|
|
2404
|
/**
|
2405
|
* @param state
|
2406
|
* @param classValue
|
2407
|
* @param byAbbrev
|
2408
|
* @return
|
2409
|
*/
|
2410
|
private Rank makeRank(MarkupImportState state, String value,
|
2411
|
boolean byAbbrev) {
|
2412
|
Rank rank = null;
|
2413
|
if (StringUtils.isBlank(value)) {
|
2414
|
return null;
|
2415
|
}
|
2416
|
try {
|
2417
|
boolean useUnknown = true;
|
2418
|
NomenclaturalCode nc = makeNomenclaturalCode(state);
|
2419
|
if (byAbbrev) {
|
2420
|
rank = Rank.getRankByAbbreviation(value, nc, useUnknown);
|
2421
|
} else {
|
2422
|
rank = Rank.getRankByEnglishName(value, nc, useUnknown);
|
2423
|
}
|
2424
|
if (rank.equals(Rank.UNKNOWN_RANK())) {
|
2425
|
rank = null;
|
2426
|
}
|
2427
|
} catch (UnknownCdmTypeException e) {
|
2428
|
// doNothing
|
2429
|
}
|
2430
|
return rank;
|
2431
|
}
|
2432
|
|
2433
|
// public void handleNameNotRank(MarkupImportState state, XMLEventReader
|
2434
|
// reader, XMLEvent parentEvent, String classValue, NonViralName name)
|
2435
|
// throws XMLStreamException {
|
2436
|
// if (ACCEPTED.equalsIgnoreCase(classValue)){
|
2437
|
// }else if (SYNONYM.equalsIgnoreCase(classValue)){
|
2438
|
// }else{
|
2439
|
// //TODO Not yet implemented
|
2440
|
// handleNotYetImplementedAttributeValue(parentEvent, CLASS, classValue);
|
2441
|
// }
|
2442
|
// }
|
2443
|
|
2444
|
private void handleCitation(MarkupImportState state, XMLEventReader reader,
|
2445
|
XMLEvent parentEvent, NonViralName name) throws XMLStreamException {
|
2446
|
String classValue = getClassOnlyAttribute(parentEvent);
|
2447
|
|
2448
|
state.setCitation(true);
|
2449
|
boolean hasRefPart = false;
|
2450
|
Map<String, String> refMap = new HashMap<String, String>();
|
2451
|
while (reader.hasNext()) {
|
2452
|
XMLEvent next = readNoWhitespace(reader);
|
2453
|
if (isMyEndingElement(next, parentEvent)) {
|
2454
|
checkMandatoryElement(hasRefPart, parentEvent.asStartElement(),
|
2455
|
REF_PART);
|
2456
|
Reference reference = createReference(state, refMap, next);
|
2457
|
String microReference = refMap.get(DETAILS);
|
2458
|
doCitation(state, name, classValue, reference, microReference,
|
2459
|
parentEvent);
|
2460
|
state.setCitation(false);
|
2461
|
return;
|
2462
|
} else if (isStartingElement(next, REF_PART)) {
|
2463
|
handleRefPart(state, reader, next, refMap);
|
2464
|
hasRefPart = true;
|
2465
|
} else {
|
2466
|
handleUnexpectedElement(next);
|
2467
|
}
|
2468
|
}
|
2469
|
throw new IllegalStateException("Citation has no closing tag");
|
2470
|
|
2471
|
}
|
2472
|
|
2473
|
private void handleRefPart(MarkupImportState state, XMLEventReader reader,XMLEvent parentEvent, Map<String, String> refMap) throws XMLStreamException {
|
2474
|
String classValue = getClassOnlyAttribute(parentEvent);
|
2475
|
|
2476
|
String text = "";
|
2477
|
while (reader.hasNext()) {
|
2478
|
XMLEvent next = readNoWhitespace(reader);
|
2479
|
if (isMyEndingElement(next, parentEvent)) {
|
2480
|
refMap.put(classValue, text);
|
2481
|
return;
|
2482
|
} else if (next.isStartElement()) {
|
2483
|
if (isStartingElement(next, ANNOTATION)) {
|
2484
|
handleNotYetImplementedElement(next);
|
2485
|
} else if (isStartingElement(next, ITALICS)) {
|
2486
|
handleNotYetImplementedElement(next);
|
2487
|
} else if (isStartingElement(next, BOLD)) {
|
2488
|
handleNotYetImplementedElement(next);
|
2489
|
} else {
|
2490
|
handleUnexpectedStartElement(next.asStartElement());
|
2491
|
}
|
2492
|
} else if (next.isCharacters()) {
|
2493
|
text += next.asCharacters().getData();
|
2494
|
} else {
|
2495
|
handleUnexpectedEndElement(next.asEndElement());
|
2496
|
}
|
2497
|
}
|
2498
|
throw new IllegalStateException("RefPart has no closing tag");
|
2499
|
|
2500
|
}
|
2501
|
|
2502
|
private Reference createReference(MarkupImportState state, Map<String, String> refMap, XMLEvent parentEvent) {
|
2503
|
// TODO
|
2504
|
Reference reference;
|
2505
|
|
2506
|
String type = getAndRemoveMapKey(refMap, PUBTYPE);
|
2507
|
String authorStr = getAndRemoveMapKey(refMap, AUTHOR);
|
2508
|
String titleStr = getAndRemoveMapKey(refMap, PUBTITLE);
|
2509
|
String titleCache = getAndRemoveMapKey(refMap, PUBFULLNAME);
|
2510
|
String volume = getAndRemoveMapKey(refMap, VOLUME);
|
2511
|
String edition = getAndRemoveMapKey(refMap, EDITION);
|
2512
|
String editors = getAndRemoveMapKey(refMap, EDITORS);
|
2513
|
String year = getAndRemoveMapKey(refMap, YEAR);
|
2514
|
String pubName = getAndRemoveMapKey(refMap, PUBNAME);
|
2515
|
|
2516
|
if (state.isCitation()) {
|
2517
|
if (volume != null || "journal".equalsIgnoreCase(type)) {
|
2518
|
IArticle article = ReferenceFactory.newArticle();
|
2519
|
if (pubName != null) {
|
2520
|
IJournal journal = ReferenceFactory.newJournal();
|
2521
|
journal.setTitle(pubName);
|
2522
|
article.setInJournal(journal);
|
2523
|
}
|
2524
|
reference = (Reference) article;
|
2525
|
|
2526
|
} else {
|
2527
|
// TODO
|
2528
|
Reference bookOrPartOf = ReferenceFactory.newGeneric();
|
2529
|
reference = bookOrPartOf;
|
2530
|
}
|
2531
|
// TODO use existing author from name or before
|
2532
|
TeamOrPersonBase author = createAuthor(authorStr);
|
2533
|
reference.setAuthorTeam(author);
|
2534
|
|
2535
|
} else {
|
2536
|
if (volume != null || "journal".equalsIgnoreCase(type)) {
|
2537
|
IArticle article = ReferenceFactory.newArticle();
|
2538
|
if (pubName != null) {
|
2539
|
IJournal journal = ReferenceFactory.newJournal();
|
2540
|
journal.setTitle(pubName);
|
2541
|
article.setInJournal(journal);
|
2542
|
}
|
2543
|
reference = (Reference) article;
|
2544
|
|
2545
|
} else {
|
2546
|
Reference bookOrPartOf = ReferenceFactory.newGeneric();
|
2547
|
reference = bookOrPartOf;
|
2548
|
}
|
2549
|
|
2550
|
// TODO type
|
2551
|
TeamOrPersonBase author = createAuthor(authorStr);
|
2552
|
reference.setAuthorTeam(author);
|
2553
|
|
2554
|
reference.setTitle(titleStr);
|
2555
|
if (StringUtils.isNotBlank(titleCache)) {
|
2556
|
reference.setTitleCache(titleCache, true);
|
2557
|
}
|
2558
|
reference.setEdition(edition);
|
2559
|
reference.setEditor(editors);
|
2560
|
|
2561
|
if (pubName != null) {
|
2562
|
Reference inReference;
|
2563
|
if (reference.getType().equals(ReferenceType.Article)) {
|
2564
|
inReference = ReferenceFactory.newJournal();
|
2565
|
} else {
|
2566
|
inReference = ReferenceFactory.newGeneric();
|
2567
|
}
|
2568
|
inReference.setTitle(pubName);
|
2569
|
reference.setInReference(inReference);
|
2570
|
}
|
2571
|
}
|
2572
|
reference.setVolume(volume);
|
2573
|
reference.setDatePublished(TimePeriod.parseString(year));
|
2574
|
|
2575
|
// TODO
|
2576
|
String[] unhandledList = new String[]{ALTERNATEPUBTITLE, ISSUE, NOTES, STATUS};
|
2577
|
for (String unhandled : unhandledList){
|
2578
|
String value = getAndRemoveMapKey(refMap, unhandled);
|
2579
|
if (isNotBlank(value)){
|
2580
|
this.handleNotYetImplementedAttributeValue(parentEvent, CLASS, unhandled);
|
2581
|
}
|
2582
|
}
|
2583
|
|
2584
|
for (String key : refMap.keySet()) {
|
2585
|
if (!DETAILS.equalsIgnoreCase(key)) {
|
2586
|
this.fireUnexpectedAttributeValue(parentEvent, CLASS, key);
|
2587
|
}
|
2588
|
}
|
2589
|
|
2590
|
return reference;
|
2591
|
}
|
2592
|
|
2593
|
private TeamOrPersonBase createAuthor(String authorTitle) {
|
2594
|
// TODO atomize and also use by name creation
|
2595
|
TeamOrPersonBase result = Team.NewTitledInstance(authorTitle,
|
2596
|
authorTitle);
|
2597
|
return result;
|
2598
|
}
|
2599
|
|
2600
|
private String getAndRemoveMapKey(Map<String, String> map, String key) {
|
2601
|
String result = map.get(key);
|
2602
|
map.remove(key);
|
2603
|
if (result != null) {
|
2604
|
result = normalize(result);
|
2605
|
}
|
2606
|
return StringUtils.stripToNull(result);
|
2607
|
}
|
2608
|
|
2609
|
private void doCitation(MarkupImportState state, NonViralName name,
|
2610
|
String classValue, Reference reference, String microCitation,
|
2611
|
XMLEvent parentEvent) {
|
2612
|
if (PUBLICATION.equalsIgnoreCase(classValue)) {
|
2613
|
name.setNomenclaturalReference(reference);
|
2614
|
name.setNomenclaturalMicroReference(microCitation);
|
2615
|
} else if (USAGE.equalsIgnoreCase(classValue)) {
|
2616
|
Taxon taxon = state.getCurrentTaxon();
|
2617
|
TaxonDescription td = this.getTaxonDescription(taxon, state
|
2618
|
.getConfig().getSourceReference(), false, true);
|
2619
|
TextData citation = TextData.NewInstance(Feature.CITATION());
|
2620
|
// TODO name used in source
|
2621
|
citation.addSource(null, null, reference, microCitation);
|
2622
|
td.addElement(citation);
|
2623
|
} else if (TYPE.equalsIgnoreCase(classValue)) {
|
2624
|
handleNotYetImplementedAttributeValue(parentEvent, CLASS,
|
2625
|
classValue);
|
2626
|
} else {
|
2627
|
// TODO Not yet implemented
|
2628
|
handleNotYetImplementedAttributeValue(parentEvent, CLASS,
|
2629
|
classValue);
|
2630
|
}
|
2631
|
}
|
2632
|
|
2633
|
private void handleFeature(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
2634
|
String classValue = getClassOnlyAttribute(parentEvent);
|
2635
|
Feature feature = makeFeature(classValue, state, parentEvent);
|
2636
|
Taxon taxon = state.getCurrentTaxon();
|
2637
|
TaxonDescription taxonDescription = getTaxonDescription(taxon, state.getConfig().getSourceReference(), NO_IMAGE_GALLERY, CREATE_NEW);
|
2638
|
// TextData figureHolderTextData = null; //for use with one TextData for
|
2639
|
// all figure only
|
2640
|
|
2641
|
boolean isDescription = feature.equals(Feature.DESCRIPTION());
|
2642
|
DescriptionElementBase lastDescriptionElement = null;
|
2643
|
|
2644
|
while (reader.hasNext()) {
|
2645
|
XMLEvent next = readNoWhitespace(reader);
|
2646
|
if (isMyEndingElement(next, parentEvent)) {
|
2647
|
return;
|
2648
|
} else if (isEndingElement(next, DISTRIBUTION_LIST) || isEndingElement(next, HABITAT_LIST)) {
|
2649
|
// only handle list elements
|
2650
|
} else if (isStartingElement(next, HEADING)) {
|
2651
|
makeFeatureHeading(state, reader, classValue, feature, next);
|
2652
|
} else if (isStartingElement(next, WRITER)) {
|
2653
|
makeFeatureWriter(state, reader, feature, taxon, next);
|
2654
|
// } else if (isStartingElement(next, DISTRIBUTION_LOCALITY)) {
|
2655
|
// if (!feature.equals(Feature.DISTRIBUTION())) {
|
2656
|
// String message = "Distribution locality only allowed for feature of type 'distribution'";
|
2657
|
// fireWarningEvent(message, next, 4);
|
2658
|
// }
|
2659
|
// handleDistributionLocality(state, reader, next);
|
2660
|
} else if (isStartingElement(next, DISTRIBUTION_LIST) || isStartingElement(next, HABITAT_LIST)) {
|
2661
|
// only handle single list elements
|
2662
|
} else if (isStartingElement(next, HABITAT)) {
|
2663
|
if (!(feature.equals(Feature.HABITAT())
|
2664
|
|| feature.equals(Feature.HABITAT_ECOLOGY())
|
2665
|
|| feature.equals(Feature.ECOLOGY()))) {
|
2666
|
String message = "Habitat only allowed for feature of type 'habitat','habitat ecology' or 'ecology'";
|
2667
|
fireWarningEvent(message, next, 4);
|
2668
|
}
|
2669
|
handleHabitat(state, reader, next);
|
2670
|
} else if (isStartingElement(next, CHAR)) {
|
2671
|
TextData textData = handleChar(state, reader, next);
|
2672
|
taxonDescription.addElement(textData);
|
2673
|
} else if (isStartingElement(next, STRING)) {
|
2674
|
lastDescriptionElement = makeFeatureString(state, reader,feature, taxonDescription, lastDescriptionElement,next);
|
2675
|
} else if (isStartingElement(next, FIGURE_REF)) {
|
2676
|
lastDescriptionElement = makeFeatureFigureRef(state, reader, taxonDescription, isDescription, lastDescriptionElement, next);
|
2677
|
} else if (isStartingElement(next, REFERENCES)) {
|
2678
|
// TODO details/microcitation ??
|
2679
|
|
2680
|
List<Reference<?>> refs = handleReferences(state, reader, next);
|
2681
|
if (!refs.isEmpty()) {
|
2682
|
// TODO
|
2683
|
Reference<?> descriptionRef = state.getConfig().getSourceReference();
|
2684
|
TaxonDescription description = getTaxonDescription(taxon, descriptionRef, false, true);
|
2685
|
TextData featurePlaceholder = getFeaturePlaceholder(state, description, feature, true);
|
2686
|
for (Reference<?> citation : refs) {
|
2687
|
featurePlaceholder.addSource(null, null, citation, null);
|
2688
|
}
|
2689
|
} else {
|
2690
|
String message = "No reference found in references";
|
2691
|
fireWarningEvent(message, next, 6);
|
2692
|
}
|
2693
|
} else if (isStartingElement(next, NUM)) {
|
2694
|
//TODO
|
2695
|
handleNotYetImplementedElement(next);
|
2696
|
} else if (isEndingElement(next, NUM)) {
|
2697
|
//TODO
|
2698
|
popUnimplemented(next.asEndElement());
|
2699
|
} else {
|
2700
|
handleUnexpectedElement(next);
|
2701
|
}
|
2702
|
}
|
2703
|
throw new IllegalStateException("<Feature> has no closing tag");
|
2704
|
}
|
2705
|
|
2706
|
/**
|
2707
|
* @param state
|
2708
|
* @param reader
|
2709
|
* @param taxonDescription
|
2710
|
* @param isDescription
|
2711
|
* @param lastDescriptionElement
|
2712
|
* @param next
|
2713
|
* @return
|
2714
|
* @throws XMLStreamException
|
2715
|
*/
|
2716
|
private DescriptionElementBase makeFeatureFigureRef(MarkupImportState state, XMLEventReader reader,TaxonDescription taxonDescription,
|
2717
|
boolean isDescription, DescriptionElementBase lastDescriptionElement, XMLEvent next)throws XMLStreamException {
|
2718
|
FigureDataHolder figureHolder = handleFigureRef(state, reader, next);
|
2719
|
Feature figureFeature = getFeature(state,MarkupTransformer.uuidFigures, "Figures", "Figures", "Fig.",null);
|
2720
|
if (isDescription) {
|
2721
|
TextData figureHolderTextData = null;
|
2722
|
// if (figureHolderTextData == null){
|
2723
|
figureHolderTextData = TextData.NewInstance(figureFeature);
|
2724
|
if (StringUtils.isNotBlank(figureHolder.num)) {
|
2725
|
String annotationText = "<num>" + figureHolder.num.trim()
|
2726
|
+ "</num>";
|
2727
|
Annotation annotation = Annotation.NewInstance(annotationText,
|
2728
|
AnnotationType.TECHNICAL(), Language.DEFAULT());
|
2729
|
figureHolderTextData.addAnnotation(annotation);
|
2730
|
}
|
2731
|
if (StringUtils.isNotBlank(figureHolder.figurePart)) {
|
2732
|
String annotationText = "<figurePart>"+ figureHolder.figurePart.trim() + "</figurePart>";
|
2733
|
Annotation annotation = Annotation.NewInstance(annotationText,AnnotationType.EDITORIAL(), Language.DEFAULT());
|
2734
|
figureHolderTextData.addAnnotation(annotation);
|
2735
|
}
|
2736
|
// if (StringUtils.isNotBlank(figureText)){
|
2737
|
// figureHolderTextData.putText(Language.DEFAULT(), figureText);
|
2738
|
// }
|
2739
|
taxonDescription.addElement(figureHolderTextData);
|
2740
|
// }
|
2741
|
registerFigureDemand(state, figureHolderTextData, figureHolder.ref);
|
2742
|
} else {
|
2743
|
if (lastDescriptionElement == null) {
|
2744
|
String message = "No description element created yet that can be referred by figure. Create new TextData instead";
|
2745
|
fireWarningEvent(message, next, 4);
|
2746
|
lastDescriptionElement = TextData.NewInstance(figureFeature);
|
2747
|
taxonDescription.addElement(lastDescriptionElement);
|
2748
|
}
|
2749
|
registerFigureDemand(state, lastDescriptionElement,
|
2750
|
figureHolder.ref);
|
2751
|
}
|
2752
|
return lastDescriptionElement;
|
2753
|
}
|
2754
|
|
2755
|
/**
|
2756
|
* @param state
|
2757
|
* @param reader
|
2758
|
* @param feature
|
2759
|
* @param taxonDescription
|
2760
|
* @param lastDescriptionElement
|
2761
|
* @param distributionList
|
2762
|
* @param next
|
2763
|
* @return
|
2764
|
* @throws XMLStreamException
|
2765
|
*/
|
2766
|
private DescriptionElementBase makeFeatureString(MarkupImportState state,XMLEventReader reader, Feature feature,
|
2767
|
TaxonDescription taxonDescription, DescriptionElementBase lastDescriptionElement, XMLEvent next) throws XMLStreamException {
|
2768
|
Map<String, String> subheadingMap = handleString(state, reader, next, feature);
|
2769
|
for (String subheading : subheadingMap.keySet()) {
|
2770
|
Feature subheadingFeature = feature;
|
2771
|
if (StringUtils.isNotBlank(subheading) && subheadingMap.size() > 1) {
|
2772
|
subheadingFeature = makeFeature(subheading, state, next);
|
2773
|
}
|
2774
|
TextData textData = TextData.NewInstance(subheadingFeature);
|
2775
|
textData.putText(Language.DEFAULT(), subheadingMap.get(subheading));
|
2776
|
taxonDescription.addElement(textData);
|
2777
|
// TODO how to handle figures when these data are split in
|
2778
|
// subheadings
|
2779
|
lastDescriptionElement = textData;
|
2780
|
}
|
2781
|
return lastDescriptionElement;
|
2782
|
}
|
2783
|
|
2784
|
/**
|
2785
|
* @param state
|
2786
|
* @param reader
|
2787
|
* @param feature
|
2788
|
* @param taxon
|
2789
|
* @param next
|
2790
|
* @throws XMLStreamException
|
2791
|
*/
|
2792
|
private void makeFeatureWriter(MarkupImportState state,XMLEventReader reader, Feature feature, Taxon taxon, XMLEvent next) throws XMLStreamException {
|
2793
|
WriterDataHolder writer = handleWriter(state, reader, next);
|
2794
|
if (isNotBlank(writer.writer)) {
|
2795
|
// TODO
|
2796
|
Reference<?> ref = state.getConfig().getSourceReference();
|
2797
|
TaxonDescription description = getTaxonDescription(taxon, ref,
|
2798
|
false, true);
|
2799
|
TextData featurePlaceholder = getFeaturePlaceholder(state,
|
2800
|
description, feature, true);
|
2801
|
featurePlaceholder.addAnnotation(writer.annotation);
|
2802
|
registerFootnotes(state, featurePlaceholder, writer.footnotes);
|
2803
|
} else {
|
2804
|
String message = "Writer element is empty";
|
2805
|
fireWarningEvent(message, next, 4);
|
2806
|
}
|
2807
|
}
|
2808
|
|
2809
|
/**
|
2810
|
* @param state
|
2811
|
* @param reader
|
2812
|
* @param classValue
|
2813
|
* @param feature
|
2814
|
* @param next
|
2815
|
* @throws XMLStreamException
|
2816
|
*/
|
2817
|
private void makeFeatureHeading(MarkupImportState state, XMLEventReader reader, String classValue, Feature feature, XMLEvent next) throws XMLStreamException {
|
2818
|
String heading = handleHeading(state, reader, next);
|
2819
|
if (StringUtils.isNotBlank(heading)) {
|
2820
|
if (!heading.equalsIgnoreCase(classValue)) {
|
2821
|
try {
|
2822
|
if (!feature.equals(state.getTransformer().getFeatureByKey(
|
2823
|
heading))) {
|
2824
|
UUID headerFeatureUuid = state.getTransformer()
|
2825
|
.getFeatureUuid(heading);
|
2826
|
if (!feature.getUuid().equals(headerFeatureUuid)) {
|
2827
|
String message = "Feature heading '%s' differs from feature class '%s' and can not be transformed to feature";
|
2828
|
message = String.format(message, heading,
|
2829
|
classValue);
|
2830
|
fireWarningEvent(message, next, 1);
|
2831
|
}
|
2832
|
}
|
2833
|
} catch (UndefinedTransformerMethodException e) {
|
2834
|
throw new RuntimeException(e);
|
2835
|
}
|
2836
|
} else {
|
2837
|
// do nothing
|
2838
|
}
|
2839
|
}
|
2840
|
}
|
2841
|
|
2842
|
private List<Reference<?>> handleReferences(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
2843
|
// attributes
|
2844
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
2845
|
String bibliography = getAndRemoveAttributeValue(attributes,
|
2846
|
BIBLIOGRAPHY);
|
2847
|
String serialsAbbreviations = getAndRemoveAttributeValue(attributes,
|
2848
|
SERIALS_ABBREVIATIONS);
|
2849
|
if (isNotBlank(bibliography) || isNotBlank(serialsAbbreviations)) {
|
2850
|
String message = "Attributes not yet implemented for <references>";
|
2851
|
fireWarningEvent(message, parentEvent, 4);
|
2852
|
}
|
2853
|
|
2854
|
List<Reference<?>> result = new ArrayList<Reference<?>>();
|
2855
|
|
2856
|
// elements
|
2857
|
while (reader.hasNext()) {
|
2858
|
XMLEvent next = readNoWhitespace(reader);
|
2859
|
if (next.isEndElement()) {
|
2860
|
if (isMyEndingElement(next, parentEvent)) {
|
2861
|
return result;
|
2862
|
} else {
|
2863
|
if (isEndingElement(next, HEADING)) {
|
2864
|
// NOT YET IMPLEMENTED
|
2865
|
popUnimplemented(next.asEndElement());
|
2866
|
} else if (isEndingElement(next, WRITER)) {
|
2867
|
// NOT YET IMPLEMENTED
|
2868
|
popUnimplemented(next.asEndElement());
|
2869
|
} else if (isEndingElement(next, FOOTNOTE)) {
|
2870
|
// NOT YET IMPLEMENTED
|
2871
|
popUnimplemented(next.asEndElement());
|
2872
|
} else if (isEndingElement(next, STRING)) {
|
2873
|
// NOT YET IMPLEMENTED
|
2874
|
popUnimplemented(next.asEndElement());
|
2875
|
} else if (isEndingElement(next, REF_NUM)) {
|
2876
|
// NOT YET IMPLEMENTED
|
2877
|
popUnimplemented(next.asEndElement());
|
2878
|
} else {
|
2879
|
handleUnexpectedEndElement(next.asEndElement());
|
2880
|
}
|
2881
|
}
|
2882
|
} else if (next.isStartElement()) {
|
2883
|
if (isStartingElement(next, HEADING)) {
|
2884
|
handleNotYetImplementedElement(next);
|
2885
|
} else if (isStartingElement(next, SUB_HEADING)) {
|
2886
|
String subheading = getCData(state, reader, next).trim();
|
2887
|
String excludePattern = "(i?)(References?|Literature):?";
|
2888
|
if (!subheading.matches(excludePattern)) {
|
2889
|
fireNotYetImplementedElement(next.getLocation(), next.asStartElement().getName(), 0);
|
2890
|
}
|
2891
|
} else if (isStartingElement(next, WRITER)) {
|
2892
|
handleNotYetImplementedElement(next);
|
2893
|
} else if (isStartingElement(next, FOOTNOTE)) {
|
2894
|
handleNotYetImplementedElement(next);
|
2895
|
} else if (isStartingElement(next, STRING)) {
|
2896
|
handleNotYetImplementedElement(next);
|
2897
|
} else if (isStartingElement(next, REF_NUM)) {
|
2898
|
handleNotYetImplementedElement(next);
|
2899
|
} else if (isStartingElement(next, REFERENCE)) {
|
2900
|
Reference<?> ref = handleReference(state, reader, next);
|
2901
|
result.add(ref);
|
2902
|
} else {
|
2903
|
handleUnexpectedStartElement(next);
|
2904
|
}
|
2905
|
} else {
|
2906
|
handleUnexpectedElement(next);
|
2907
|
}
|
2908
|
}
|
2909
|
throw new IllegalStateException("<References> has no closing tag");
|
2910
|
}
|
2911
|
|
2912
|
private void handleHabitat(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
2913
|
checkNoAttributes(parentEvent);
|
2914
|
Taxon taxon = state.getCurrentTaxon();
|
2915
|
// TODO which ref to take?
|
2916
|
Reference<?> ref = state.getConfig().getSourceReference();
|
2917
|
|
2918
|
String text = "";
|
2919
|
while (reader.hasNext()) {
|
2920
|
XMLEvent next = readNoWhitespace(reader);
|
2921
|
if (isMyEndingElement(next, parentEvent)) {
|
2922
|
TaxonDescription description = getTaxonDescription(taxon, ref,
|
2923
|
false, true);
|
2924
|
UUID uuidExtractedHabitat = MarkupTransformer.uuidExtractedHabitat;
|
2925
|
Feature feature = getFeature(
|
2926
|
state,
|
2927
|
uuidExtractedHabitat,
|
2928
|
"Extracted Habitat",
|
2929
|
"An structured habitat that was extracted from a habitat text",
|
2930
|
"extr. habit.", null);
|
2931
|
TextData habitat = TextData.NewInstance(feature);
|
2932
|
habitat.putText(Language.DEFAULT(), text);
|
2933
|
description.addElement(habitat);
|
2934
|
|
2935
|
return;
|
2936
|
} else if (next.isStartElement()) {
|
2937
|
if (isStartingElement(next, ALTITUDE)) {
|
2938
|
text = text.trim() + getTaggedCData(state, reader, next);
|
2939
|
} else if (isStartingElement(next, LIFE_CYCLE_PERIODS)) {
|
2940
|
handleNotYetImplementedElement(next);
|
2941
|
} else {
|
2942
|
handleUnexpectedStartElement(next.asStartElement());
|
2943
|
}
|
2944
|
} else if (next.isCharacters()) {
|
2945
|
text += next.asCharacters().getData();
|
2946
|
} else {
|
2947
|
handleUnexpectedElement(next);
|
2948
|
}
|
2949
|
}
|
2950
|
throw new IllegalStateException("<Habitat> has no closing tag");
|
2951
|
}
|
2952
|
|
2953
|
private String getTaggedCData(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
|
2954
|
checkNoAttributes(parentEvent);
|
2955
|
|
2956
|
String text = getXmlTag(parentEvent);
|
2957
|
while (reader.hasNext()) {
|
2958
|
XMLEvent next = readNoWhitespace(reader);
|
2959
|
if (isMyEndingElement(next, parentEvent)) {
|
2960
|
text += getXmlTag(next);
|
2961
|
return text;
|
2962
|
} else if (next.isStartElement()) {
|
2963
|
text += getTaggedCData(state, reader, next);
|
2964
|
} else if (next.isEndElement()) {
|
2965
|
text += getTaggedCData(state, reader, next);
|
2966
|
} else if (next.isCharacters()) {
|
2967
|
text += next.asCharacters().getData();
|
2968
|
} else {
|
2969
|
handleUnexpectedEndElement(next.asEndElement());
|
2970
|
}
|
2971
|
}
|
2972
|
throw new IllegalStateException("Some tag has no closing tag");
|
2973
|
|
2974
|
}
|
2975
|
|
2976
|
private void handleDistributionLocality(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent)throws XMLStreamException {
|
2977
|
Map<String, Attribute> attributes = getAttributes(parentEvent);
|
2978
|
String classValue = getAndRemoveRequiredAttributeValue(parentEvent, attributes, CLASS);
|
2979
|
String statusValue =getAndRemoveAttributeValue(attributes, STATUS);
|
2980
|
String frequencyValue =getAndRemoveAttributeValue(attributes, FREQUENCY);
|
2981
|
|
2982
|
|
2983
|
Taxon taxon = state.getCurrentTaxon();
|
2984
|
// TODO which ref to take?
|
2985
|
Reference<?> ref = state.getConfig().getSourceReference();
|
2986
|
|
2987
|
String text = "";
|
2988
|
while (reader.hasNext()) {
|
2989
|
XMLEvent next = readNoWhitespace(reader);
|
2990
|
if (isMyEndingElement(next, parentEvent)) {
|
2991
|
if (StringUtils.isNotBlank(text)) {
|
2992
|
TaxonDescription description = getTaxonDescription(taxon, ref, false, true);
|
2993
|
NamedAreaLevel level = makeNamedAreaLevel(state,classValue, next);
|
2994
|
NamedArea area = createArea(text, level, state);
|
2995
|
|
2996
|
PresenceAbsenceTermBase<?> status = null;
|
2997
|
try {
|
2998
|
status = state.getTransformer().getPresenceTermByKey(statusValue);
|
2999
|
} catch (UndefinedTransformerMethodException e) {
|
3000
|
throw new RuntimeException(e);
|
3001
|
}
|
3002
|
Distribution distribution = Distribution.NewInstance(area,status);
|
3003
|
description.addElement(distribution);
|
3004
|
if (isNotBlank(frequencyValue)){
|
3005
|
String message = "The frequency attribute is currently not yet available in CDM";
|
3006
|
fireWarningEvent(message, parentEvent, 6);
|
3007
|
}
|
3008
|
} else {
|
3009
|
String message = "Empty distribution locality";
|
3010
|
fireWarningEvent(message, next, 4);
|
3011
|
}
|
3012
|
return;
|
3013
|
} else if (isStartingElement(next, COORDINATES)) {
|
3014
|
//TODO
|
3015
|
handleNotYetImplementedElement(next);
|
3016
|
} else if (isEndingElement(next, COORDINATES)) {
|
3017
|
//TODO
|
3018
|
popUnimplemented(next.asEndElement());
|
3019
|
} else if (next.isCharacters()) {
|
3020
|
text += next.asCharacters().getData();
|
3021
|
} else {
|
3022
|
handleUnexpectedEndElement(next.asEndElement());
|
3023
|
}
|
3024
|
}
|
3025
|
throw new IllegalStateException("<DistributionLocality> has no closing tag");
|
3026
|
}
|
3027
|
|
3028
|
/**
|
3029
|
* @param state
|
3030
|
* @param levelString
|
3031
|
* @param next
|
3032
|
* @return
|
3033
|
*/
|
3034
|
private NamedAreaLevel makeNamedAreaLevel(MarkupImportState state,
|
3035
|
String levelString, XMLEvent next) {
|
3036
|
NamedAreaLevel level;
|
3037
|
try {
|
3038
|
level = state.getTransformer().getNamedAreaLevelByKey(levelString);
|
3039
|
if (level == null) {
|
3040
|
UUID levelUuid = state.getTransformer().getNamedAreaLevelUuid(levelString);
|
3041
|
if (levelUuid == null) {
|
3042
|
String message = "Unknown distribution locality class (named area level): %s. Create new level instead.";
|
3043
|
message = String.format(message, levelString);
|
3044
|
fireWarningEvent(message, next, 6);
|
3045
|
}
|
3046
|
level = getNamedAreaLevel(state, levelUuid, levelString,
|
3047
|
levelString, levelString, null);
|
3048
|
}
|
3049
|
} catch (UndefinedTransformerMethodException e) {
|
3050
|
throw new RuntimeException(e);
|
3051
|
}
|
3052
|
return level;
|
3053
|
}
|
3054
|
|
3055
|
private String handleHeading(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent)throws XMLStreamException {
|
3056
|
checkNoAttributes(parentEvent);
|
3057
|
|
3058
|
String text = "";
|
3059
|
while (reader.hasNext()) {
|
3060
|
XMLEvent next = readNoWhitespace(reader);
|
3061
|
if (isMyEndingElement(next, parentEvent)) {
|
3062
|
return text;
|
3063
|
} else if (next.isStartElement()) {
|
3064
|
if (isStartingElement(next, FOOTNOTE)) {
|
3065
|
handleNotYetImplementedElement(next);
|
3066
|
} else {
|
3067
|
handleUnexpectedStartElement(next.asStartElement());
|
3068
|
}
|
3069
|
} else if (next.isCharacters()) {
|
3070
|
text += next.asCharacters().getData();
|
3071
|
} else {
|
3072
|
handleUnexpectedEndElement(next.asEndElement());
|
3073
|
}
|
3074
|
}
|
3075
|
throw new IllegalStateException("<String> has no closing tag");
|
3076
|
|
3077
|
}
|
3078
|
|
3079
|
/**
|
3080
|
* Handle string
|
3081
|
* @param state
|
3082
|
* @param reader
|
3083
|
* @param parentEvent
|
3084
|
* @param feature only needed for distributionLocalities
|
3085
|
* @return
|
3086
|
* @throws XMLStreamException
|
3087
|
*/
|
3088
|
private Map<String, String> handleString(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, Feature feature)throws XMLStreamException {
|
3089
|
// attributes
|
3090
|
String classValue = getClassOnlyAttribute(parentEvent, false);
|
3091
|
if (StringUtils.isNotBlank(classValue)) {
|
3092
|
String message = "class attribute for <string> not yet implemented";
|
3093
|
fireWarningEvent(message, parentEvent, 2);
|
3094
|
}
|
3095
|
|
3096
|
// subheadings
|
3097
|
Map<String, String> subHeadingMap = new HashMap<String, String>();
|
3098
|
String currentSubheading = null;
|
3099
|
|
3100
|
boolean isTextMode = true;
|
3101
|
String text = "";
|
3102
|
while (reader.hasNext()) {
|
3103
|
XMLEvent next = readNoWhitespace(reader);
|
3104
|
if (isMyEndingElement(next, parentEvent)) {
|
3105
|
putCurrentSubheading(subHeadingMap, currentSubheading, text);
|
3106
|
return subHeadingMap;
|
3107
|
} else if (isStartingElement(next, BR)) {
|
3108
|
text += "<br/>";
|
3109
|
isTextMode = false;
|
3110
|
} else if (isEndingElement(next, BR)) {
|
3111
|
isTextMode = true;
|
3112
|
} else if (isHtml(next)) {
|
3113
|
text += getXmlTag(next);
|
3114
|
} else if (isStartingElement(next, SUB_HEADING)) {
|
3115
|
text = putCurrentSubheading(subHeadingMap,currentSubheading, text);
|
3116
|
// TODO footnotes
|
3117
|
currentSubheading = getCData(state, reader, next).trim();
|
3118
|
} else if (isStartingElement(next, DISTRIBUTION_LOCALITY)) {
|
3119
|
if (feature != null && !feature.equals(Feature.DISTRIBUTION())) {
|
3120
|
String message = "Distribution locality only allowed for feature of type 'distribution'";
|
3121
|
fireWarningEvent(message, next, 4);
|
3122
|
}
|
3123
|
handleDistributionLocality(state, reader, next);
|
3124
|
|
3125
|
} else if (next.isCharacters()) {
|
3126
|
if (!isTextMode) {
|
3127
|
String message = "String is not in text mode";
|
3128
|
fireWarningEvent(message, next, 6);
|
3129
|
} else {
|
3130
|
text += next.asCharacters().getData();
|
3131
|
}
|
3132
|
} else if (isStartingElement(next, HEADING)) {
|
3133
|
//TODO
|
3134
|
handleNotYetImplementedElement(next);
|
3135
|
} else if (isEndingElement(next, HEADING)) {
|
3136
|
//TODO
|
3137
|
popUnimplemented(next.asEndElement());
|
3138
|
} else if (isStartingElement(next, QUOTE)) {
|
3139
|
//TODO
|
3140
|
handleNotYetImplementedElement(next);
|
3141
|
} else if (isEndingElement(next, QUOTE)) {
|
3142
|
//TODO
|
3143
|
popUnimplemented(next.asEndElement());
|
3144
|
} else if (isStartingElement(next, DEDICATION)) {
|
3145
|
//TODO
|
3146
|
handleNotYetImplementedElement(next);
|
3147
|
} else if (isEndingElement(next, DEDICATION)) {
|
3148
|
//TODO
|
3149
|
popUnimplemented(next.asEndElement());
|
3150
|
} else if (isStartingElement(next, TAXONTYPE)) {
|
3151
|
//TODO
|
3152
|
handleNotYetImplementedElement(next);
|
3153
|
} else if (isEndingElement(next, TAXONTYPE)) {
|
3154
|
//TODO
|
3155
|
popUnimplemented(next.asEndElement());
|
3156
|
} else if (isStartingElement(next, FULL_NAME)) {
|
3157
|
//TODO
|
3158
|
handleNotYetImplementedElement(next);
|
3159
|
} else if (isEndingElement(next, FULL_NAME)) {
|
3160
|
//TODO
|
3161
|
popUnimplemented(next.asEndElement());
|
3162
|
}else if (isStartingElement(next, REFERENCES)) {
|
3163
|
//TODO
|
3164
|
handleNotYetImplementedElement(next);
|
3165
|
} else if (isEndingElement(next, REFERENCES)) {
|
3166
|
//TODO
|
3167
|
popUnimplemented(next.asEndElement());
|
3168
|
} else if (isStartingElement(next, GATHERING)) {
|
3169
|
//TODO
|
3170
|
handleNotYetImplementedElement(next);
|
3171
|
} else if (isEndingElement(next, GATHERING)) {
|
3172
|
//TODO
|
3173
|
popUnimplemented(next.asEndElement());
|
3174
|
} else if (isStartingElement(next, ANNOTATION)) {
|
3175
|
//TODO
|
3176
|
handleNotYetImplementedElement(next);
|
3177
|
} else if (isEndingElement(next, ANNOTATION)) {
|
3178
|
//TODO
|
3179
|
popUnimplemented(next.asEndElement());
|
3180
|
} else if (isStartingElement(next, HABITAT)) {
|
3181
|
//TODO
|
3182
|
handleNotYetImplementedElement(next);
|
3183
|
} else if (isEndingElement(next, HABITAT)) {
|
3184
|
//TODO
|
3185
|
popUnimplemented(next.asEndElement());
|
3186
|
} else if (isStartingElement(next, FIGURE_REF)) {
|
3187
|
//TODO
|
3188
|
handleNotYetImplementedElement(next);
|
3189
|
} else if (isEndingElement(next, FIGURE_REF)) {
|
3190
|
//TODO
|
3191
|
popUnimplemented(next.asEndElement());
|
3192
|
} else if (isStartingElement(next, FIGURE)) {
|
3193
|
//TODO
|
3194
|
handleNotYetImplementedElement(next);
|
3195
|
} else if (isEndingElement(next, FIGURE)) {
|
3196
|
//TODO
|
3197
|
popUnimplemented(next.asEndElement());
|
3198
|
} else if (isStartingElement(next, FOOTNOTE_REF)) {
|
3199
|
//TODO
|
3200
|
handleNotYetImplementedElement(next);
|
3201
|
} else if (isEndingElement(next, FOOTNOTE_REF)) {
|
3202
|
//TODO
|
3203
|
popUnimplemented(next.asEndElement());
|
3204
|
} else if (isStartingElement(next, FOOTNOTE)) {
|
3205
|
//TODO
|
3206
|
handleNotYetImplementedElement(next);
|
3207
|
} else if (isEndingElement(next, FOOTNOTE)) {
|
3208
|
//TODO
|
3209
|
popUnimplemented(next.asEndElement());
|
3210
|
} else if (isStartingElement(next, WRITER)) {
|
3211
|
//TODO
|
3212
|
handleNotYetImplementedElement(next);
|
3213
|
} else if (isEndingElement(next, WRITER)) {
|
3214
|
//TODO
|
3215
|
popUnimplemented(next.asEndElement());
|
3216
|
} else if (isStartingElement(next, DATES)) {
|
3217
|
//TODO
|
3218
|
handleNotYetImplementedElement(next);
|
3219
|
} else if (isEndingElement(next, DATES)) {
|
3220
|
//TODO
|
3221
|
popUnimplemented(next.asEndElement());
|
3222
|
} else {
|
3223
|
handleUnexpectedElement(next);
|
3224
|
}
|
3225
|
}
|
3226
|
throw new IllegalStateException("<String> has no closing tag");
|
3227
|
}
|
3228
|
|
3229
|
/**
|
3230
|
* @param subHeadingMap
|
3231
|
* @param currentSubheading
|
3232
|
* @param text
|
3233
|
* @return
|
3234
|
*/
|
3235
|
private String putCurrentSubheading(Map<String, String> subHeadingMap, String currentSubheading, String text) {
|
3236
|
if (StringUtils.isNotBlank(text)) {
|
3237
|
text = removeStartingMinus(text);
|
3238
|
subHeadingMap.put(currentSubheading, text.trim());
|
3239
|
}
|
3240
|
return "";
|
3241
|
}
|
3242
|
|
3243
|
private String removeStartingMinus(String string) {
|
3244
|
string = replaceStart(string, "-");
|
3245
|
string = replaceStart(string, "\u002d");
|
3246
|
string = replaceStart(string, "\u2013");
|
3247
|
string = replaceStart(string, "\u2014");
|
3248
|
string = replaceStart(string, "--");
|
3249
|
return string;
|
3250
|
}
|
3251
|
|
3252
|
/**
|
3253
|
* @param value
|
3254
|
* @param replacementString
|
3255
|
*/
|
3256
|
private String replaceStart(String value, String replacementString) {
|
3257
|
if (value.startsWith(replacementString) ){
|
3258
|
value = value.substring(replacementString.length()).trim();
|
3259
|
}
|
3260
|
while (value.startsWith("-") || value.startsWith("\u2014") ){
|
3261
|
value = value.substring("-".length()).trim();
|
3262
|
}
|
3263
|
return value;
|
3264
|
}
|
3265
|
|
3266
|
private String getXmlTag(XMLEvent event) {
|
3267
|
String result;
|
3268
|
if (event.isStartElement()) {
|
3269
|
result = "<" + event.asStartElement().getName().getLocalPart()
|
3270
|
+ ">";
|
3271
|
} else if (event.isEndElement()) {
|
3272
|
result = "</" + event.asEndElement().getName().getLocalPart() + ">";
|
3273
|
} else {
|
3274
|
String message = "Only start or end elements are allowed as Html tags";
|
3275
|
throw new IllegalStateException(message);
|
3276
|
}
|
3277
|
return result;
|
3278
|
}
|
3279
|
|
3280
|
protected static final List<String> htmlList = Arrays.asList("sub", "sup",
|
3281
|
"ol", "ul", "li", "i", "b", "table", "br");
|
3282
|
|
3283
|
private boolean isHtml(XMLEvent event) {
|
3284
|
if (event.isStartElement()) {
|
3285
|
String tag = event.asStartElement().getName().getLocalPart();
|
3286
|
return htmlList.contains(tag);
|
3287
|
} else if (event.isEndElement()) {
|
3288
|
String tag = event.asEndElement().getName().getLocalPart();
|
3289
|
return htmlList.contains(tag);
|
3290
|
} else {
|
3291
|
return false;
|
3292
|
}
|
3293
|
|
3294
|
}
|
3295
|
|
3296
|
private TextData handleChar(MarkupImportState state, XMLEventReader reader,
|
3297
|
XMLEvent parentEvent) throws XMLStreamException {
|
3298
|
String classValue = getClassOnlyAttribute(parentEvent);
|
3299
|
Feature feature = makeFeature(classValue, state, parentEvent);
|
3300
|
|
3301
|
String text = "";
|
3302
|
while (reader.hasNext()) {
|
3303
|
XMLEvent next = readNoWhitespace(reader);
|
3304
|
if (isMyEndingElement(next, parentEvent)) {
|
3305
|
TextData textData = TextData.NewInstance(feature);
|
3306
|
textData.putText(Language.DEFAULT(), text);
|
3307
|
return textData;
|
3308
|
} else if (isStartingElement(next, FIGURE_REF)) {
|
3309
|
//TODO
|
3310
|
handleNotYetImplementedElement(next);
|
3311
|
} else if (isEndingElement(next, FIGURE_REF)) {
|
3312
|
//TODO
|
3313
|
popUnimplemented(next.asEndElement());
|
3314
|
} else if (next.isStartElement()) {
|
3315
|
if (isStartingElement(next, ANNOTATION)) {
|
3316
|
handleNotYetImplementedElement(next);
|
3317
|
} else if (isStartingElement(next, ITALICS)) {
|
3318
|
handleNotYetImplementedElement(next);
|
3319
|
} else if (isStartingElement(next, BOLD)) {
|
3320
|
handleNotYetImplementedElement(next);
|
3321
|
} else {
|
3322
|
handleUnexpectedStartElement(next.asStartElement());
|
3323
|
}
|
3324
|
} else if (next.isCharacters()) {
|
3325
|
text += next.asCharacters().getData();
|
3326
|
} else {
|
3327
|
handleUnexpectedEndElement(next.asEndElement());
|
3328
|
}
|
3329
|
}
|
3330
|
throw new IllegalStateException("RefPart has no closing tag");
|
3331
|
}
|
3332
|
|
3333
|
/**
|
3334
|
* @param classValue
|
3335
|
* @param state
|
3336
|
* @param parentEvent
|
3337
|
* @return
|
3338
|
* @throws UndefinedTransformerMethodException
|
3339
|
*/
|
3340
|
private Feature makeFeature(String classValue, MarkupImportState state, XMLEvent parentEvent) {
|
3341
|
UUID uuid;
|
3342
|
try {
|
3343
|
Feature feature = state.getTransformer().getFeatureByKey(classValue);
|
3344
|
if (feature != null) {
|
3345
|
return feature;
|
3346
|
}
|
3347
|
uuid = state.getTransformer().getFeatureUuid(classValue);
|
3348
|
if (uuid == null) {
|
3349
|
// TODO
|
3350
|
String message = "Uuid is not defined for %s";
|
3351
|
message = String.format(message, classValue);
|
3352
|
fireWarningEvent(message, parentEvent, 8);
|
3353
|
}
|
3354
|
String featureText = StringUtils.capitalize(classValue);
|
3355
|
|
3356
|
// TODO eFlora vocabulary
|
3357
|
TermVocabulary<Feature> voc = null;
|
3358
|
feature = getFeature(state, uuid, featureText, featureText, classValue, voc);
|
3359
|
if (feature == null) {
|
3360
|
throw new NullPointerException(classValue + " not recognized as a feature");
|
3361
|
}
|
3362
|
return feature;
|
3363
|
} catch (Exception e) {
|
3364
|
String message = "Could not create feature for %s: %s";
|
3365
|
message = String.format(message, classValue, e.getMessage());
|
3366
|
fireWarningEvent(message, parentEvent, 4);
|
3367
|
return Feature.UNKNOWN();
|
3368
|
}
|
3369
|
}
|
3370
|
|
3371
|
/**
|
3372
|
* This comes from the old version, needs to be checked on need
|
3373
|
*
|
3374
|
* @param state
|
3375
|
*/
|
3376
|
private void doAllTheOldOtherStuff(MarkupImportState state) {
|
3377
|
state.putTree(null, null);
|
3378
|
if (unmatchedLeads == null) {
|
3379
|
unmatchedLeads = UnmatchedLeads.NewInstance();
|
3380
|
}
|
3381
|
state.setUnmatchedLeads(unmatchedLeads);
|
3382
|
|
3383
|
// TransactionStatus tx = startTransaction();
|
3384
|
unmatchedLeads.saveToSession(getPolytomousKeyNodeService());
|
3385
|
|
3386
|
// TODO generally do not store the reference object in the config
|
3387
|
Reference sourceReference = state.getConfig().getSourceReference();
|
3388
|
getReferenceService().saveOrUpdate(sourceReference);
|
3389
|
}
|
3390
|
|
3391
|
/*
|
3392
|
* (non-Javadoc)
|
3393
|
*
|
3394
|
* @see
|
3395
|
* eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common
|
3396
|
* .IImportConfigurator)
|
3397
|
*/
|
3398
|
protected boolean isIgnore(MarkupImportState state) {
|
3399
|
return !state.getConfig().isDoTaxa();
|
3400
|
}
|
3401
|
|
3402
|
}
|