Merged the latest changes from the trunk into the branch ui-gwt
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / markup / MarkupImportBase.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.io.markup;
11
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Stack;
19 import java.util.UUID;
20
21 import javax.xml.namespace.QName;
22 import javax.xml.stream.Location;
23 import javax.xml.stream.XMLEventReader;
24 import javax.xml.stream.XMLStreamConstants;
25 import javax.xml.stream.XMLStreamException;
26 import javax.xml.stream.events.Attribute;
27 import javax.xml.stream.events.EndElement;
28 import javax.xml.stream.events.StartElement;
29 import javax.xml.stream.events.XMLEvent;
30
31 import org.apache.commons.lang.StringUtils;
32 import org.apache.commons.lang.WordUtils;
33 import org.apache.log4j.Logger;
34
35 import eu.etaxonomy.cdm.api.service.IClassificationService;
36 import eu.etaxonomy.cdm.api.service.ITermService;
37 import eu.etaxonomy.cdm.common.CdmUtils;
38 import eu.etaxonomy.cdm.ext.geo.GeoServiceArea;
39 import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
40 import eu.etaxonomy.cdm.io.common.CdmImportBase;
41 import eu.etaxonomy.cdm.io.common.CdmImportBase.TermMatchMode;
42 import eu.etaxonomy.cdm.io.common.events.IIoEvent;
43 import eu.etaxonomy.cdm.io.common.events.IoProblemEvent;
44 import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
45 import eu.etaxonomy.cdm.model.agent.Team;
46 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
47 import eu.etaxonomy.cdm.model.common.AnnotationType;
48 import eu.etaxonomy.cdm.model.common.CdmBase;
49 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
50 import eu.etaxonomy.cdm.model.common.ExtensionType;
51 import eu.etaxonomy.cdm.model.common.Language;
52 import eu.etaxonomy.cdm.model.common.TermVocabulary;
53 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
54 import eu.etaxonomy.cdm.model.description.Feature;
55 import eu.etaxonomy.cdm.model.description.PolytomousKey;
56 import eu.etaxonomy.cdm.model.description.TaxonDescription;
57 import eu.etaxonomy.cdm.model.location.NamedArea;
58 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
59 import eu.etaxonomy.cdm.model.location.NamedAreaType;
60 import eu.etaxonomy.cdm.model.media.Media;
61 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
62 import eu.etaxonomy.cdm.model.name.NonViralName;
63 import eu.etaxonomy.cdm.model.name.Rank;
64 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
65 import eu.etaxonomy.cdm.model.reference.Reference;
66 import eu.etaxonomy.cdm.model.taxon.Classification;
67 import eu.etaxonomy.cdm.model.taxon.Taxon;
68 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
69 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
70
71 /**
72 * @author a.mueller
73 * @created 04.08.2008
74 */
75 public abstract class MarkupImportBase {
76 @SuppressWarnings("unused")
77 private static final Logger logger = Logger.getLogger(MarkupImportBase.class);
78
79 //Base
80 protected static final String ALTITUDE = "altitude";
81 protected static final String ANNOTATION = "annotation";
82 protected static final String BOLD = "bold";
83 protected static final String BR = "br";
84 protected static final String CITATION = "citation";
85 protected static final String CLASS = "class";
86 protected static final String COORDINATES = "coordinates";
87 protected static final String DATES = "dates";
88 protected static final String GATHERING = "gathering";
89 protected static final String GENUS_ABBREVIATION = "genus abbreviation";
90 protected static final String FOOTNOTE = "footnote";
91 protected static final String FOOTNOTE_REF = "footnoteRef";
92 protected static final String FULL_NAME = "fullName";
93 protected static final String ITALICS = "italics";
94 protected static final String NUM = "num";
95 protected static final String NOTES = "notes";
96 protected static final String PUBLICATION = "publication";
97 protected static final String SPECIMEN_TYPE = "specimenType";
98 protected static final String STATUS = "status";
99 protected static final String SUB_HEADING = "subHeading";
100 protected static final String TYPE = "type";
101 protected static final String TYPE_STATUS = "typeStatus";
102
103 protected static final boolean CREATE_NEW = true;
104 protected static final boolean NO_IMAGE_GALLERY = false;
105 protected static final boolean IMAGE_GALLERY = true;
106
107 protected static final String ADDENDA = "addenda";
108 protected static final String BIBLIOGRAPHY = "bibliography";
109 protected static final String BIOGRAPHIES = "biographies";
110 protected static final String CHAR = "char";
111 protected static final String DEDICATION = "dedication";
112 protected static final String DEFAULT_MEDIA_URL = "defaultMediaUrl";
113 protected static final String DISTRIBUTION_LIST = "distributionList";
114 protected static final String DISTRIBUTION_LOCALITY = "distributionLocality";
115 protected static final String FEATURE = "feature";
116 protected static final String FIGURE = "figure";
117 protected static final String FIGURE_LEGEND = "figureLegend";
118 protected static final String FIGURE_PART = "figurePart";
119 protected static final String FIGURE_REF = "figureRef";
120 protected static final String FIGURE_TITLE = "figureTitle";
121 protected static final String FOOTNOTE_STRING = "footnoteString";
122 protected static final String FREQUENCY = "frequency";
123 protected static final String HEADING = "heading";
124 protected static final String HABITAT = "habitat";
125 protected static final String HABITAT_LIST = "habitatList";
126 protected static final String IS_FREETEXT = "isFreetext";
127 protected static final String ID = "id";
128 protected static final String KEY = "key";
129 protected static final String LIFE_CYCLE_PERIODS = "lifeCyclePeriods";
130 protected static final String META_DATA = "metaData";
131 protected static final String MODS = "mods";
132
133 protected static final String NOMENCLATURE = "nomenclature";
134 protected static final String QUOTE = "quote";
135 protected static final String RANK = "rank";
136 protected static final String REF = "ref";
137 protected static final String REF_NUM = "refNum";
138 protected static final String REFERENCE = "reference";
139 protected static final String REFERENCES = "references";
140 protected static final String SUB_CHAR = "subChar";
141 protected static final String TAXON = "taxon";
142 protected static final String TAXONTITLE = "taxontitle";
143 protected static final String TAXONTYPE = "taxontype";
144 protected static final String TEXT_SECTION = "textSection";
145 protected static final String TREATMENT = "treatment";
146 protected static final String SERIALS_ABBREVIATIONS = "serialsAbbreviations";
147 protected static final String STRING = "string";
148 protected static final String URL = "url";
149 protected static final String VERNACULAR_NAMES = "vernacularNames";
150 protected static final String WRITER = "writer";
151
152
153 //Nomenclature
154 protected static final String ACCEPTED = "accepted";
155 protected static final String ACCEPTED_NAME = "acceptedName";
156 protected static final String ALTERNATEPUBTITLE = "alternatepubtitle";
157 protected static final String AUTHOR = "author";
158 protected static final String DETAILS = "details";
159 protected static final String EDITION = "edition";
160 protected static final String EDITORS = "editors";
161 protected static final String HOMONYM = "homonym";
162 protected static final String HOMOTYPES = "homotypes";
163 protected static final String INFRANK = "infrank";
164 protected static final String INFRAUT = "infraut";
165 protected static final String INFRPARAUT = "infrparaut";
166 protected static final String ISSUE = "issue";
167 protected static final String NAME = "name";
168 protected static final String NAME_TYPE = "nameType";
169 protected static final String NOM = "nom";
170 protected static final String PAGES = "pages";
171 protected static final String PARAUT = "paraut";
172 protected static final String PUBFULLNAME = "pubfullname";
173 protected static final String PUBNAME = "pubname";
174 protected static final String PUBTITLE = "pubtitle";
175 protected static final String PUBTYPE = "pubtype";
176 protected static final String REF_PART = "refPart";
177 protected static final String SYNONYM = "synonym";
178 protected static final String USAGE = "usage";
179 protected static final String VOLUME = "volume";
180 protected static final String YEAR = "year";
181
182
183 //keys
184 protected static final String COUPLET = "couplet";
185 protected static final String IS_SPOTCHARACTERS = "isSpotcharacters";
186 protected static final String ONLY_NUMBERED_TAXA_EXIST = "onlyNumberedTaxaExist";
187 protected static final String EXISTS = "exists";
188 protected static final String KEYNOTES = "keynotes";
189 protected static final String KEY_TITLE = "keyTitle";
190 protected static final String QUESTION = "question";
191 protected static final String TEXT = "text";
192 protected static final String TO_COUPLET = "toCouplet";
193 protected static final String TO_KEY = "toKey";
194 protected static final String TO_TAXON = "toTaxon";
195
196
197
198 protected MarkupDocumentImport docImport;
199 private IEditGeoService editGeoService;
200
201 public MarkupImportBase(MarkupDocumentImport docImport) {
202 super();
203 this.docImport = docImport;
204 this.editGeoService = docImport.getEditGeoService();
205 }
206
207 private Stack<QName> unhandledElements = new Stack<QName>();
208 private Stack<QName> handledElements = new Stack<QName>();
209
210
211 protected <T extends CdmBase> void save(Collection<T> collection, MarkupImportState state) {
212 if (state.isCheck() || collection.isEmpty()){
213 return;
214 }
215 T example = collection.iterator().next();
216 if (example.isInstanceOf(TaxonBase.class)){
217 Collection<TaxonBase> typedCollection = (Collection<TaxonBase>)collection;
218 docImport.getTaxonService().saveOrUpdate(typedCollection);
219 }else if (example.isInstanceOf(Classification.class)){
220 Collection<Classification> typedCollection = (Collection<Classification>)collection;
221 docImport.getClassificationService().saveOrUpdate(typedCollection);
222 }else if (example.isInstanceOf(PolytomousKey.class)){
223 Collection<PolytomousKey> typedCollection = (Collection<PolytomousKey>)collection;
224 docImport.getPolytomousKeyService().saveOrUpdate(typedCollection);
225 }else if (example.isInstanceOf(DefinedTermBase.class)){
226 Collection<DefinedTermBase> typedCollection = (Collection<DefinedTermBase>)collection;
227 getTermService().saveOrUpdate(typedCollection);
228 }
229
230 }
231
232
233
234 //TODO move to service layer for all IdentifiableEntities
235 protected void save(CdmBase cdmBase, MarkupImportState state) {
236 if (state.isCheck()){
237 return;
238 }
239 cdmBase = CdmBase.deproxy(cdmBase, CdmBase.class);
240 if (cdmBase == null){
241 String message = "Tried to save a null object.";
242 fireWarningEvent(message, "--location ?? --", 6,1);
243 } else if (cdmBase.isInstanceOf(TaxonBase.class)){
244 docImport.getTaxonService().saveOrUpdate((TaxonBase<?>)cdmBase);
245 }else if (cdmBase.isInstanceOf(Classification.class)){
246 docImport.getClassificationService().saveOrUpdate((Classification)cdmBase);
247 }else if (cdmBase.isInstanceOf(PolytomousKey.class)){
248 docImport.getPolytomousKeyService().saveOrUpdate((PolytomousKey)cdmBase);
249 }else if (cdmBase.isInstanceOf(DefinedTermBase.class)){
250 docImport.getTermService().saveOrUpdate((DefinedTermBase<?>)cdmBase);
251 }else if (cdmBase.isInstanceOf(Media.class)){
252 docImport.getMediaService().saveOrUpdate((Media)cdmBase);
253 }else if (cdmBase.isInstanceOf(SpecimenOrObservationBase.class)){
254 docImport.getOccurrenceService().saveOrUpdate((SpecimenOrObservationBase<?>)cdmBase);
255 }else if (cdmBase.isInstanceOf(DescriptionElementBase.class)){
256 docImport.getDescriptionService().saveDescriptionElement((DescriptionElementBase)cdmBase);
257 }else{
258 String message = "Unknown cdmBase type to save: " + cdmBase.getClass();
259 fireWarningEvent(message, "Unknown location", 8);
260 }
261 //logger.warn("Saved " + cdmBase);
262 }
263
264
265 protected ITermService getTermService() {
266 return docImport.getTermService();
267 }
268
269 protected IClassificationService getClassificationService() {
270 return docImport.getClassificationService();
271 }
272
273 //*********************** Attribute methods *************************************/
274
275 /**
276 * Returns a map for all attributes of an start element
277 * @param event
278 * @return
279 */
280 protected Map<String, Attribute> getAttributes(XMLEvent event) {
281 Map<String, Attribute> result = new HashMap<String, Attribute>();
282 if (!event.isStartElement()){
283 fireWarningEvent("Event is not an startElement. Can't check attributes", makeLocationStr(event.getLocation()), 1, 1);
284 return result;
285 }
286 StartElement element = event.asStartElement();
287 Iterator<Attribute> attributes = element.getAttributes();
288 while (attributes.hasNext()){
289 Attribute attribute = attributes.next();
290 //TODO namespaces
291 result.put(attribute.getName().getLocalPart(), attribute);
292 }
293 return result;
294 }
295
296 /**
297 * Throws an unexpected attributes event if the event has any attributes.
298 * @param event
299 */
300 protected void checkNoAttributes(Map<String, Attribute> attributes, XMLEvent event) {
301 String[] exceptions = new String[]{};
302 handleUnexpectedAttributes(event.getLocation(), attributes, 1, exceptions);
303 }
304
305
306
307 /**
308 * Throws an unexpected attributes event if the event has any attributes.
309 * @param event
310 */
311 protected void checkNoAttributes(XMLEvent event) {
312 String[] exceptions = new String[]{};
313 checkNoAttributes(event, 1, exceptions);
314 }
315
316 /**
317 * Throws an unexpected attributes event if the event has any attributes except those mentioned in "exceptions".
318 * @param event
319 * @param exceptions
320 */
321 protected void checkNoAttributes(XMLEvent event, int stackDepth, String... exceptions) {
322 if (! event.isStartElement()){
323 fireWarningEvent("Event is not an startElement. Can't check attributes", makeLocationStr(event.getLocation()), 1, 1);
324 return;
325 }
326 StartElement startElement = event.asStartElement();
327 Map<String, Attribute> attributes = getAttributes(startElement);
328 handleUnexpectedAttributes(startElement.getLocation(), attributes, stackDepth+1, exceptions);
329 }
330
331
332 /**
333 * Checks if the given attribute exists and has the given value.
334 * If yes, true is returned and the attribute is removed from the attributes map.
335 * Otherwise false is returned.
336 * @param attributes
337 * @param attrName
338 * @param value
339 * @return <code>true</code> if attribute has given value, <code>false</code> otherwise
340 */
341 protected boolean checkAndRemoveAttributeValue( Map<String, Attribute> attributes, String attrName, String value) {
342 Attribute attr = attributes.get(attrName);
343 if (attr == null ||value == null ){
344 return false;
345 }else{
346 if (value.equals(attr.getValue())){
347 attributes.remove(attrName);
348 return true;
349 }else{
350 return false;
351 }
352 }
353 }
354
355
356 /**
357 * Returns the value of a given attribute name and removes the attribute from the attributes map.
358 * @param attributes
359 * @param attrName
360 * @return
361 */
362 protected String getAndRemoveAttributeValue(Map<String, Attribute> attributes, String attrName) {
363 return getAndRemoveAttributeValue(null, attributes, attrName, false, 1);
364 }
365
366 /**
367 * Returns the value of a boolean attribute with the given name and removes the attribute from the attributes map.
368 * Returns <code>defaultValue</code> if the attribute does not exist. ALso returns <code>defaultValue</code> and throws a warning if the
369 * attribute has no boolean value (true, false).
370 * @param
371 * @param attributes the
372 * @param attrName the name of the attribute
373 * @param defaultValue the default value to return if attribute does not exist or can not be defined
374 * @return
375 */
376 protected Boolean getAndRemoveBooleanAttributeValue(XMLEvent event, Map<String, Attribute> attributes, String attrName, Boolean defaultValue) {
377 String value = getAndRemoveAttributeValue(null, attributes, attrName, false, 1);
378 Boolean result = defaultValue;
379 if (value != null){
380 if (value.equalsIgnoreCase("true")){
381 result = true;
382 }else if (value.equalsIgnoreCase("false")){
383 result = false;
384 }else{
385 String message = "Boolean attribute has no boolean value ('true', 'false') but '%s'";
386 fireWarningEvent(String.format(message, value), makeLocationStr(event.getLocation()), 6, 1);
387 }
388 }
389 return result;
390 }
391
392
393 /**
394 * Returns the value of a given attribute name and returns the attribute from the attributes map.
395 * Fires a mandatory field is missing event if the attribute does not exist.
396 * @param xmlEvent
397 * @param attributes
398 * @param attrName
399 * @return
400 */
401 protected String getAndRemoveRequiredAttributeValue(XMLEvent xmlEvent, Map<String, Attribute> attributes, String attrName) {
402 return getAndRemoveAttributeValue(xmlEvent, attributes, attrName, true, 1);
403 }
404
405 /**
406 * Returns the value of a given attribute name and returns the attribute from the attributes map.
407 * If required is <code>true</code> and the attribute does not exist a mandatory field is missing event is fired.
408 * @param xmlEvent
409 * @param attributes
410 * @param attrName
411 * @param isRequired
412 * @return
413 */
414 private String getAndRemoveAttributeValue(XMLEvent xmlEvent, Map<String, Attribute> attributes, String attrName, boolean isRequired, int stackDepth) {
415 Attribute attr = attributes.get(attrName);
416 if (attr == null ){
417 if (isRequired){
418 fireMandatoryElementIsMissing(xmlEvent, attrName, 8, stackDepth+1);
419 }
420 return null;
421 }else{
422 attributes.remove(attrName);
423 return attr.getValue();
424 }
425 }
426
427 /**
428 * Fires an not yet implemented event if the given attribute exists in attributes.
429 * @param attributes
430 * @param attrName
431 */
432 protected void handleNotYetImplementedAttribute(Map<String, Attribute> attributes, String attrName) {
433 Attribute attr = attributes.get(attrName);
434 if (attr != null){
435 attributes.remove(attrName);
436 QName qName = attr.getName();
437 fireNotYetImplementedAttribute(attr.getLocation(), qName, 1);
438 }
439 }
440
441 /**
442 * Fires an unhandled attributes event, if attributes exist in attributes map not covered by the exceptions.
443 * No event is fired if the unhandled elements stack is not empty.
444 * @param location
445 * @param attributes
446 * @param exceptions
447 */
448 protected void handleUnexpectedAttributes(Location location,Map<String, Attribute> attributes, String... exceptions) {
449 handleUnexpectedAttributes(location, attributes, 1, exceptions);
450 }
451
452 /**
453 * see {@link #handleUnexpectedAttributes(Location, Map, String...)}
454 *
455 * @param location
456 * @param attributes
457 * @param stackDepth the stack trace depth
458 * @param exceptions
459 */
460 private void handleUnexpectedAttributes(Location location,Map<String, Attribute> attributes, int stackDepth, String... exceptions) {
461 if (attributes.size() > 0){
462 if (this.unhandledElements.size() == 0 ){
463 boolean hasUnhandledAttributes = false;
464 for (String key : attributes.keySet()){
465 boolean isException = false;
466 for (String exception : exceptions){
467 if(key.equals(exception)){
468 isException = true;
469 }
470 }
471 if (!isException){
472 hasUnhandledAttributes = true;
473 }
474 }
475 if (hasUnhandledAttributes){
476 fireUnexpectedAttributes(location, attributes, stackDepth+1);
477 }
478 }
479 }
480 }
481
482
483 private void fireUnexpectedAttributes(Location location, Map<String, Attribute> attributes, int stackDepth) {
484 String attributesString = "";
485 for (String key : attributes.keySet()){
486 Attribute attribute = attributes.get(key);
487 attributesString = CdmUtils.concat(",", attributesString, attribute.getName().getLocalPart() + ":" + attribute.getValue());
488 }
489 String message = "Unexpected attributes: %s";
490 IoProblemEvent event = makeProblemEvent(location, String.format(message, attributesString), 1 , stackDepth +1 );
491 fire(event);
492 }
493
494
495 protected void fireUnexpectedAttributeValue(XMLEvent parentEvent, String attrName, String attrValue) {
496 String message = "Unexpected attribute value %s='%s'";
497 message = String.format(message, attrName, attrValue);
498 IoProblemEvent event = makeProblemEvent(parentEvent.getLocation(), message, 1 , 1 );
499 fire(event);
500 }
501
502 protected void handleNotYetImplementedAttributeValue(XMLEvent xmlEvent, String attrName, String attrValue) {
503 String message = "Attribute %s not yet implemented for value '%s'";
504 message = String.format(message, attrName, attrValue);
505 IIoEvent event = makeProblemEvent(xmlEvent.getLocation(), message, 1, 1 );
506 fire(event);
507 }
508
509 protected void fireNotYetImplementedAttribute(Location location, QName qName, int stackDepth) {
510 String message = "Attribute not yet implemented: %s";
511 IIoEvent event = makeProblemEvent(location, String.format(message, qName.getLocalPart()), 1, stackDepth+1 );
512 fire(event);
513 }
514
515
516
517
518 protected void fireUnexpectedEvent(XMLEvent xmlEvent, int stackDepth) {
519 Location location = xmlEvent.getLocation();
520 String message = "Unexpected event: %s";
521 IIoEvent event = makeProblemEvent(location, String.format(message, xmlEvent.toString()), 2, stackDepth +1);
522 fire(event);
523 }
524
525 protected void fireUnexpectedStartElement(Location location, StartElement startElement, int stackDepth) {
526 QName qName = startElement.getName();
527 String message = "Unexpected start element: %s";
528 IIoEvent event = makeProblemEvent(location, String.format(message, qName.getLocalPart()), 2, stackDepth +1);
529 fire(event);
530 }
531
532
533 protected void fireUnexpectedEndElement(Location location, EndElement endElement, int stackDepth) {
534 QName qName = endElement.getName();
535 String message = "Unexpected end element: %s";
536 IIoEvent event = makeProblemEvent(location, String.format(message, qName.getLocalPart()), 16, stackDepth+1);
537 fire(event);
538 }
539
540
541 protected void fireNotYetImplementedElement(Location location, QName qName, int stackDepth) {
542 String message = "Element not yet implemented: %s";
543 IIoEvent event = makeProblemEvent(location, String.format(message, qName.getLocalPart()), 1, stackDepth+1 );
544 fire(event);
545 }
546
547 /**
548 * Creates a problem event.
549 * Be aware of the right depths of the stack trace !
550 * @param location
551 * @param message
552 * @param severity
553 * @return
554 */
555 private IoProblemEvent makeProblemEvent(Location location, String message, int severity, int stackDepth) {
556 stackDepth++;
557 StackTraceElement[] stackTrace = new Exception().getStackTrace();
558 int lineNumber = stackTrace[stackDepth].getLineNumber();
559 String methodName = stackTrace[stackDepth].getMethodName();
560 String locationStr = makeLocationStr(location);
561 IoProblemEvent event = IoProblemEvent.NewInstance(this.getClass(), message,
562 locationStr, lineNumber, severity, methodName);
563 return event;
564 }
565
566 /**
567 * Creates a string from a location
568 * @param location
569 * @return
570 */
571 protected String makeLocationStr(Location location) {
572 String locationStr = location == null ? " - no location - " : "l." + location.getLineNumber() + "/c."+ location.getColumnNumber();
573 return locationStr;
574 }
575
576
577 /**
578 * Fires an unexpected element event if the unhandled elements stack is empty.
579 * Otherwise adds the element to the stack.
580 * @param event
581 */
582 protected void handleUnexpectedStartElement(XMLEvent event) {
583 handleUnexpectedStartElement(event, 1);
584 }
585
586 /**
587 * Fires an unexpected element event if the unhandled elements stack is empty.
588 * Otherwise adds the element to the stack.
589 * @param event
590 */
591 protected void handleUnexpectedStartElement(XMLEvent event, int stackDepth) {
592 QName qName = event.asStartElement().getName();
593 if (! unhandledElements.empty()){
594 unhandledElements.push(qName);
595 }else{
596 fireUnexpectedStartElement(event.getLocation(), event.asStartElement(), stackDepth + 1);
597 }
598 }
599
600
601 protected void handleUnexpectedEndElement(EndElement event) {
602 handleUnexpectedEndElement(event, 1);
603 }
604
605 /**
606 * Fires an unexpected element event if the event is not the last on the stack.
607 * Otherwise removes last stack element.
608 * @param event
609 */
610 protected void handleUnexpectedEndElement(EndElement event, int stackDepth) {
611 QName qName = event.asEndElement().getName();
612 if (!unhandledElements.isEmpty() && unhandledElements.peek().equals(qName)){
613 unhandledElements.pop();
614 }else{
615 fireUnexpectedEndElement(event.getLocation(), event.asEndElement(), stackDepth + 1);
616 }
617 }
618
619 /**
620 *
621 * @param endElement
622 */
623 protected void popUnimplemented(EndElement endElement) {
624 QName qName = endElement.asEndElement().getName();
625 if (unhandledElements.peek().equals(qName)){
626 unhandledElements.pop();
627 }else{
628 String message = "End element is not last on stack: %s";
629 message = String.format(message, qName.getLocalPart());
630 IIoEvent event = makeProblemEvent(endElement.getLocation(), message, 16, 1);
631 fire(event);
632 }
633
634 }
635
636
637 /**
638 * Fires an unexpected element event if the unhandled element stack is empty.
639 * @param event
640 */
641 protected void handleUnexpectedElement(XMLEvent event) {
642 if (event.isStartElement()){
643 handleUnexpectedStartElement(event);
644 }else if (event.isEndElement()){
645 handleUnexpectedEndElement(event.asEndElement());
646 }else if (event.getEventType() == XMLStreamConstants.COMMENT){
647 //do nothing
648 }else if (! unhandledElements.empty()){
649 //do nothing
650 }else{
651 fireUnexpectedEvent(event, 1);
652 }
653 }
654
655 /**
656 * Fires an not yet implemented event and adds the element name to the unhandled elements stack.
657 * @param event
658 */
659 protected void handleNotYetImplementedElement(XMLEvent event) {
660 QName qName = event.asStartElement().getName();
661 boolean isTopLevel = unhandledElements.isEmpty();
662 unhandledElements.push(qName);
663 if (isTopLevel){
664 fireNotYetImplementedElement(event.getLocation(), qName, 1);
665 }
666 }
667
668 /**
669 * Checks if a mandatory text is not empty or null.
670 * Returns true if text is given.
671 * Fires an mandatory element is missing event otherwise and returns <code>null</code>.
672 * @param text
673 * @param parentEvent
674 * @return
675 */
676 protected boolean checkMandatoryText(String text, XMLEvent parentEvent) {
677 if (! StringUtils.isNotBlank(text)){
678 fireMandatoryElementIsMissing(parentEvent, "CData", 4, 1);
679 return false;
680 }
681 return true;
682 }
683
684 /**
685 * Fires an mandatory element is missing event if exists is <code>false</code>.
686 * @param hasMandatory
687 * @param parentEvent
688 * @param string
689 */
690 protected void checkMandatoryElement(boolean exists, StartElement parentEvent, String attrName) {
691 if (! exists){
692 fireMandatoryElementIsMissing(parentEvent, attrName, 5, 1);
693 }
694 }
695
696
697 /**
698 * Fires an element is missing event.
699 * @param xmlEvent
700 * @param string
701 * @param severity
702 * @param stackDepth
703 * @throws IllegalStateException if xmlEvent is not a StartElement and not an Attribute
704 */
705 private void fireMandatoryElementIsMissing(XMLEvent xmlEvent, String missingEventName, int severity, int stackDepth) throws IllegalStateException{
706 Location location = xmlEvent.getLocation();
707 String typeName;
708 QName qName;
709 if (xmlEvent.isAttribute()){
710 Attribute attribute = ((Attribute)xmlEvent);
711 typeName = "attribute";
712 qName = attribute.getName();
713 }else if (xmlEvent.isStartElement()){
714 typeName = "element";
715 qName = xmlEvent.asStartElement().getName();
716 }else{
717 throw new IllegalStateException("mandatory element only allowed for attributes and start tags in " + makeLocationStr(location));
718 }
719 String message = "Mandatory %s '%s' is missing in %s";
720 message = String.format(message, typeName , missingEventName, qName.getLocalPart());
721 IIoEvent event = makeProblemEvent(location, message, severity, stackDepth +1);
722 fire(event);
723 }
724
725
726
727
728 /**
729 * Returns true if the "next" event is the ending tag for the "parent" event.
730 * @param next end element to test, must not be null
731 * @param parentEvent start element to test
732 * @return true if the "next" event is the ending tag for the "parent" event.
733 * @throws XMLStreamException
734 */
735 protected boolean isMyEndingElement(XMLEvent next, XMLEvent parentEvent) throws XMLStreamException {
736 if (! parentEvent.isStartElement()){
737 String message = "Parent event should be start tag";
738 fireWarningEvent(message, makeLocationStr(next.getLocation()), 6);
739 return false;
740 }
741 return isEndingElement(next, parentEvent.asStartElement().getName().getLocalPart());
742 }
743
744 /**
745 * Trims the text and removes turns all whitespaces into single empty space.
746 * @param text
747 * @return
748 */
749 protected String normalize(String text) {
750 text = StringUtils.trimToEmpty(text);
751 text = text.replaceAll("\\s+", " ");
752 return text;
753 }
754
755
756
757 /**
758 * Removes whitespaces at beginning and end and makes the first letter
759 * a capital letter and all other letters small letters.
760 * @param value
761 * @return
762 */
763 protected String toFirstCapital(String value) {
764 if (StringUtils.isBlank(value)){
765 return value;
766 }else{
767 String result = "";
768 value = value.trim();
769 result += value.trim().substring(0,1).toUpperCase();
770 if (value.length()>1){
771 result += value.substring(1).toLowerCase();
772 }
773 return result;
774 }
775 }
776
777 /**
778 * Currently not used.
779 * @param str
780 * @param allowedNumberOfCharacters
781 * @param onlyFirstCapital
782 * @return
783 */
784 protected boolean isAbbreviation(String str, int allowedNumberOfCharacters, boolean onlyFirstCapital){
785 if (isBlank(str)){
786 return false;
787 }
788 str = str.trim();
789 if (! str.endsWith(".")){
790 return false;
791 }
792 str = str.substring(0, str.length() -1);
793 if (str.length() > allowedNumberOfCharacters){
794 return false;
795 }
796 final String re = "^\\p{javaUpperCase}\\p{javaLowerCase}*$";
797 if (str.matches(re)){
798 return true;
799 }else{
800 return false;
801 }
802 }
803
804 /**
805 * Checks if <code>abbrev</code> is the short form for the genus name (strGenusName).
806 * Usually this is the case if <code>abbrev</code> is the first letter (optional with ".")
807 * of strGenusName. But in older floras it may also be the first 2 or 3 letters (optional with dot).
808 * However, we allow only a maximum of 2 letters to be anambigous. In cases with 3 letters better
809 * change the original markup data.
810 * @param single
811 * @param strGenusName
812 * @return
813 */
814 protected boolean isGenusAbbrev(String abbrev, String strGenusName) {
815 if (! abbrev.matches("[A-Z][a-z]?\\.?")) {
816 return false;
817 }else if (abbrev.length() == 0 || strGenusName == null || strGenusName.length() == 0){
818 return false;
819 }else{
820 abbrev = abbrev.replace(".", "");
821 return strGenusName.startsWith(abbrev);
822 // boolean result = true;
823 // for (int i = 0 ; i < abbrev.length(); i++){
824 // result &= ( abbrev.charAt(i) == strGenusName.charAt(i));
825 // }
826 // return result;
827 }
828 }
829
830
831 /**
832 * Checks if all words in the given string start with a capital letter but do not have any further capital letter.
833 * @param word the string to be checekd. Usually should be a single word.
834 * @return true if the above is the case, false otherwise
835 */
836 protected boolean isFirstCapitalWord(String word) {
837 if (WordUtils.capitalizeFully(word).equals(word)){
838 return true;
839 }else if (WordUtils.capitalizeFully(word,new char[]{'-'}).equals(word)){
840 //for words like Le-Testui (which is a species epithet)
841 return true;
842 }else{
843 return false;
844 }
845 }
846
847
848 /**
849 * Read next event. Ignore whitespace events.
850 * @param reader
851 * @return
852 * @throws XMLStreamException
853 */
854 protected XMLEvent readNoWhitespace(XMLEventReader reader) throws XMLStreamException {
855 XMLEvent event = reader.nextEvent();
856 while (event.isCharacters() && event.asCharacters().isWhiteSpace()){
857 event = reader.nextEvent();
858 }
859 return event;
860 }
861
862 /**
863 * Returns the REQUIRED "class" attribute for a given event and checks that it is the only attribute.
864 * @param parentEvent
865 * @return
866 */
867 protected String getClassOnlyAttribute(XMLEvent parentEvent) {
868 return getClassOnlyAttribute(parentEvent, true);
869 }
870
871
872 /**
873 * Returns the "class" attribute for a given event and checks that it is the only attribute.
874 * @param parentEvent
875 * @return
876 */
877 protected String getClassOnlyAttribute(XMLEvent parentEvent, boolean required) {
878 return getOnlyAttribute(parentEvent, CLASS, required);
879 }
880
881 /**
882 * Returns the value for the only attribute for a given event and checks that it is the only attribute.
883 * @param parentEvent
884 * @return
885 */
886 protected String getOnlyAttribute(XMLEvent parentEvent, String attrName, boolean required) {
887 Map<String, Attribute> attributes = getAttributes(parentEvent);
888 String classValue =getAndRemoveAttributeValue(parentEvent, attributes, attrName, required, 1);
889 checkNoAttributes(attributes, parentEvent);
890 return classValue;
891 }
892
893
894 protected void fireWarningEvent(String message, String locationStr, Integer severity, Integer depth) {
895 docImport.fireWarningEvent(message, locationStr, severity, depth);
896 }
897
898 protected void fireWarningEvent(String message, XMLEvent event, Integer severity) {
899 docImport.fireWarningEvent(message, makeLocationStr(event.getLocation()), severity, 1);
900 }
901
902 protected void fireSchemaConflictEventExpectedStartTag(String elName, XMLEventReader reader) throws XMLStreamException {
903 docImport.fireSchemaConflictEventExpectedStartTag(elName, reader);
904 }
905
906
907 protected void fireWarningEvent(String message, String locationStr, int severity) {
908 docImport.fireWarningEvent(message, locationStr, severity, 1);
909 }
910
911 protected void fire(IIoEvent event) {
912 docImport.fire(event);
913 }
914
915 protected boolean isNotBlank(String str){
916 return StringUtils.isNotBlank(str);
917 }
918
919 protected boolean isBlank(String str){
920 return StringUtils.isBlank(str);
921 }
922
923 public TaxonDescription getTaxonDescription(Taxon taxon, Reference<?> ref, boolean isImageGallery, boolean createNewIfNotExists) {
924 return docImport.getTaxonDescription(taxon, isImageGallery, createNewIfNotExists);
925 }
926
927
928 /**
929 * Returns the default language defined in the state. If no default language is defined in the state,
930 * the CDM default language is returned.
931 * @param state
932 * @return
933 */
934 protected Language getDefaultLanguage(MarkupImportState state) {
935 Language result = state.getDefaultLanguage();
936 if (result == null){
937 result = Language.DEFAULT();
938 }
939 return result;
940 }
941
942
943 //*********************** FROM XML IMPORT BASE ****************************************
944 protected boolean isEndingElement(XMLEvent event, String elName) throws XMLStreamException {
945 return docImport.isEndingElement(event, elName);
946 }
947
948 protected boolean isStartingElement(XMLEvent event, String elName) throws XMLStreamException {
949 return docImport.isStartingElement(event, elName);
950 }
951
952
953 protected void fillMissingEpithetsForTaxa(Taxon parentTaxon, Taxon childTaxon) {
954 docImport.fillMissingEpithetsForTaxa(parentTaxon, childTaxon);
955 }
956
957 protected Feature getFeature(MarkupImportState state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<Feature> voc){
958 return docImport.getFeature(state, uuid, label, text, labelAbbrev, voc);
959 }
960
961 protected ExtensionType getExtensionType(MarkupImportState state, UUID uuid, String label, String text, String labelAbbrev){
962 return docImport.getExtensionType(state, uuid, label, text, labelAbbrev);
963 }
964
965 protected AnnotationType getAnnotationType(MarkupImportState state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<AnnotationType> voc){
966 return docImport.getAnnotationType(state, uuid, label, text, labelAbbrev, voc);
967 }
968
969 protected NamedAreaLevel getNamedAreaLevel(MarkupImportState state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<NamedAreaLevel> voc){
970 return docImport.getNamedAreaLevel(state, uuid, label, text, labelAbbrev, voc);
971 }
972
973 protected NamedArea getNamedArea(MarkupImportState state, UUID uuid, String label, String text, String labelAbbrev, NamedAreaType areaType, NamedAreaLevel level, TermVocabulary voc, TermMatchMode matchMode){
974 return docImport.getNamedArea(state, uuid, label, text, labelAbbrev, areaType, level, voc, matchMode);
975 }
976
977 protected Language getLanguage(MarkupImportState state, UUID uuid, String label, String text, String labelAbbrev, TermVocabulary<?> voc){
978 return docImport.getLanguage(state, uuid, label, text, labelAbbrev, voc);
979 }
980
981 // *************************************** Concrete methods **********************************************/
982
983
984 /**
985 * @param state
986 * @param classValue
987 * @param byAbbrev
988 * @return
989 */
990 protected Rank makeRank(MarkupImportState state, String value, boolean byAbbrev) {
991 Rank rank = null;
992 if (StringUtils.isBlank(value)) {
993 return null;
994 }
995 try {
996 boolean useUnknown = true;
997 NomenclaturalCode nc = makeNomenclaturalCode(state);
998 if (value.equals(GENUS_ABBREVIATION)){
999 rank = Rank.GENUS();
1000 }else if (byAbbrev) {
1001 rank = Rank.getRankByAbbreviation(value, nc, useUnknown);
1002 } else {
1003 rank = Rank.getRankByEnglishName(value, nc, useUnknown);
1004 }
1005 if (rank.equals(Rank.UNKNOWN_RANK())) {
1006 rank = null;
1007 }
1008 } catch (UnknownCdmTypeException e) {
1009 // doNothing
1010 }
1011 return rank;
1012 }
1013
1014
1015
1016 protected TeamOrPersonBase<?> createAuthor(String authorTitle) {
1017 // TODO atomize and also use by name creation
1018 TeamOrPersonBase<?> result = Team.NewTitledInstance(authorTitle, authorTitle);
1019 return result;
1020 }
1021
1022 protected String getAndRemoveMapKey(Map<String, String> map, String key) {
1023 String result = map.get(key);
1024 map.remove(key);
1025 if (result != null) {
1026 result = normalize(result);
1027 }
1028 return StringUtils.stripToNull(result);
1029 }
1030
1031
1032 /**
1033 * Creates a {@link NonViralName} object depending on the defined {@link NomenclaturalCode}
1034 * and the given parameters.
1035 * @param state
1036 * @param rank
1037 * @return
1038 */
1039 protected NonViralName<?> createNameByCode(MarkupImportState state, Rank rank) {
1040 NonViralName<?> name;
1041 NomenclaturalCode nc = makeNomenclaturalCode(state);
1042 name = (NonViralName<?>) nc.getNewTaxonNameInstance(rank);
1043 return name;
1044 }
1045
1046
1047 /**
1048 * Returns the {@link NomenclaturalCode} for this import. Default is {@link NomenclaturalCode#ICBN} if
1049 * no code is defined.
1050 * @param state
1051 * @return
1052 */
1053 protected NomenclaturalCode makeNomenclaturalCode(MarkupImportState state) {
1054 NomenclaturalCode nc = state.getConfig().getNomenclaturalCode();
1055 if (nc == null) {
1056 nc = NomenclaturalCode.ICBN; // default;
1057 }
1058 return nc;
1059 }
1060
1061
1062 /**
1063 * @param state
1064 * @param levelString
1065 * @param next
1066 * @return
1067 */
1068 protected NamedAreaLevel makeNamedAreaLevel(MarkupImportState state,
1069 String levelString, XMLEvent next) {
1070 NamedAreaLevel level;
1071 try {
1072 level = state.getTransformer().getNamedAreaLevelByKey(levelString);
1073 if (level == null) {
1074 UUID levelUuid = state.getTransformer().getNamedAreaLevelUuid(levelString);
1075 if (levelUuid == null) {
1076 String message = "Unknown distribution locality class (named area level): %s. Create new level instead.";
1077 message = String.format(message, levelString);
1078 fireWarningEvent(message, next, 6);
1079 }
1080 level = getNamedAreaLevel(state, levelUuid, levelString, levelString, levelString, null);
1081 }
1082 } catch (UndefinedTransformerMethodException e) {
1083 throw new RuntimeException(e);
1084 }
1085 return level;
1086 }
1087
1088
1089 /**
1090 * @param state
1091 * @param areaName
1092 * @param level
1093 * @return
1094 */
1095 protected NamedArea makeArea(MarkupImportState state, String areaName, NamedAreaLevel level) {
1096
1097 //TODO FM vocabulary
1098 TermVocabulary<NamedArea> voc = null;
1099 NamedAreaType areaType = null;
1100
1101 NamedArea area = null;
1102 try {
1103 area = state.getTransformer().getNamedAreaByKey(areaName);
1104 } catch (UndefinedTransformerMethodException e) {
1105 throw new RuntimeException(e);
1106 }
1107 if (area == null){
1108 boolean isNewInState = false;
1109 UUID uuid = state.getAreaUuid(areaName);
1110 if (uuid == null){
1111 isNewInState = true;
1112
1113
1114 try {
1115 uuid = state.getTransformer().getNamedAreaUuid(areaName);
1116 } catch (UndefinedTransformerMethodException e) {
1117 throw new RuntimeException(e);
1118 }
1119 }
1120
1121 CdmImportBase.TermMatchMode matchMode = CdmImportBase.TermMatchMode.UUID_LABEL;
1122 area = getNamedArea(state, uuid, areaName, areaName, areaName, areaType, level, voc, matchMode);
1123 if (isNewInState){
1124 state.putAreaUuid(areaName, area.getUuid());
1125
1126 //TODO just for testing -> make generic and move to better place
1127 String geoServiceLayer="vmap0_as_bnd_political_boundary_a";
1128 String layerFieldName ="nam";
1129
1130 if ("Bangka".equals(areaName)){
1131 String areaValue = "PULAU BANGKA#SUMATERA SELATAN";
1132 GeoServiceArea geoServiceArea = new GeoServiceArea();
1133 geoServiceArea.add(geoServiceLayer, layerFieldName, areaValue);
1134 this.editGeoService.setMapping(area, geoServiceArea);
1135 // save(area, state);
1136 }
1137 if ("Luzon".equals(areaName)){
1138 GeoServiceArea geoServiceArea = new GeoServiceArea();
1139
1140 List<String> list = Arrays.asList("HERMANA MAYOR ISLAND#CENTRAL LUZON",
1141 "HERMANA MENOR ISLAND#CENTRAL LUZON",
1142 "CENTRAL LUZON");
1143 for (String areaValue : list){
1144 geoServiceArea.add(geoServiceLayer, layerFieldName, areaValue);
1145 }
1146
1147 this.editGeoService.setMapping(area, geoServiceArea);
1148 // save(area, state);
1149 }
1150 if ("Mindanao".equals(areaName)){
1151 GeoServiceArea geoServiceArea = new GeoServiceArea();
1152
1153 List<String> list = Arrays.asList("NORTHERN MINDANAO",
1154 "SOUTHERN MINDANAO",
1155 "WESTERN MINDANAO");
1156 //TODO to be continued
1157 for (String areaValue : list){
1158 geoServiceArea.add(geoServiceLayer, layerFieldName, areaValue);
1159 }
1160
1161 this.editGeoService.setMapping(area, geoServiceArea);
1162 // save(area, state);
1163 }
1164 if ("Palawan".equals(areaName)){
1165 GeoServiceArea geoServiceArea = new GeoServiceArea();
1166
1167 List<String> list = Arrays.asList("PALAWAN#SOUTHERN TAGALOG");
1168 for (String areaValue : list){
1169 geoServiceArea.add(geoServiceLayer, layerFieldName, areaValue);
1170 }
1171
1172 this.editGeoService.setMapping(area, geoServiceArea);
1173 // save(area, state);
1174 }
1175
1176 }
1177 }
1178 return area;
1179 }
1180
1181
1182
1183 /**
1184 * Reads character data. Any element other than character data or the ending
1185 * tag will fire an unexpected element event.
1186 *
1187 * @see #getCData(MarkupImportState, XMLEventReader, XMLEvent, boolean)
1188 * @param state
1189 * @param reader
1190 * @param next
1191 * @return
1192 * @throws XMLStreamException
1193 */
1194 protected String getCData(MarkupImportState state, XMLEventReader reader, XMLEvent next) throws XMLStreamException {
1195 return getCData(state, reader, next, true);
1196 }
1197
1198 /**
1199 * Reads character data. Any element other than character data or the ending
1200 * tag will fire an unexpected element event.
1201 *
1202 * @param state
1203 * @param reader
1204 * @param next
1205 * @param inlineMarkup map for inline markup, this is used for e.g. the locality markup within a subheading
1206 * The map will be filled by the markup element name as key. The value may be a String, a CdmBase or any other object.
1207 * If null any markup text will be neglected but a warning will be fired if they exist.
1208 * @param removeInlineMarkupText if true the markedup text will be removed from the returned String
1209 * @param checkAttributes
1210 * @return
1211 * @throws XMLStreamException
1212 */
1213 protected String getCData(MarkupImportState state, XMLEventReader reader, XMLEvent parent, /*Map<String, Object> inlineMarkup, *boolean removeInlineMarkupText,*/ boolean checkAttributes) throws XMLStreamException {
1214 if (checkAttributes){
1215 checkNoAttributes(parent);
1216 }
1217
1218 String text = "";
1219 while (reader.hasNext()) {
1220 XMLEvent next = readNoWhitespace(reader);
1221 if (isMyEndingElement(next, parent)) {
1222 return text;
1223 } else if (next.isCharacters()) {
1224 text += next.asCharacters().getData();
1225 } else if (isStartingElement(next, FOOTNOTE_REF)){
1226 handleNotYetImplementedElement(next);
1227 // } else if (isStartingElement(next, LOCALITY)){
1228 // handleCDataLocality(state, reader, parent);
1229 } else {
1230 handleUnexpectedElement(next);
1231 }
1232 }
1233 throw new IllegalStateException("Event has no closing tag");
1234
1235 }
1236
1237 // private void handleCDataLocality(MarkupImportState state, XMLEventReader reader, XMLEvent parent) {
1238 // checkAndRemoveAttributeValue(attributes, attrName, value)
1239 //
1240 // }
1241
1242
1243
1244 /**
1245 * For it returns a pure CData annotation string. This behaviour may change in future. More complex annotations
1246 * should be handled differently.
1247 * @param state
1248 * @param reader
1249 * @param parentEvent
1250 * @return
1251 * @throws XMLStreamException
1252 */
1253 protected String handleSimpleAnnotation(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {
1254 String annotation = getCData(state, reader, parentEvent);
1255 return annotation;
1256 }
1257
1258 /**
1259 * True if text is single "." oder "," or ";" or ":"
1260 * @param text
1261 * @return
1262 */
1263 protected boolean isPunctuation(String text) {
1264 return text == null ? false : text.trim().matches("^[\\.,;:]$");
1265 }
1266
1267
1268
1269 //********************************************** OLD *************************************
1270
1271 // protected boolean testAdditionalElements(Element parentElement, List<String> excludeList){
1272 // boolean result = true;
1273 // List<Element> list = parentElement.getChildren();
1274 // for (Element element : list){
1275 // if (! excludeList.contains(element.getName())){
1276 // logger.warn("Unknown element (" + element.getName() + ") in parent element (" + parentElement.getName() + ")");
1277 // result = false;
1278 // }
1279 // }
1280 // return result;
1281 // }
1282 //
1283 //
1284 // protected <T extends IdentifiableEntity> T makeReferenceType(Element element, Class<? extends T> clazz, MapWrapper<? extends T> objectMap, ResultWrapper<Boolean> success){
1285 // T result = null;
1286 // String linkType = element.getAttributeValue("linkType");
1287 // String ref = element.getAttributeValue("ref");
1288 // if(ref == null && linkType == null){
1289 // result = getInstance(clazz);
1290 // if (result != null){
1291 // String title = element.getTextNormalize();
1292 // result.setTitleCache(title, true);
1293 // }
1294 // }else if (linkType == null || linkType.equals("local")){
1295 // //TODO
1296 // result = objectMap.get(ref);
1297 // if (result == null){
1298 // logger.warn("Object (ref = " + ref + ")could not be found in WrapperMap");
1299 // }
1300 // }else if(linkType.equals("external")){
1301 // logger.warn("External link types not yet implemented");
1302 // }else if(linkType.equals("other")){
1303 // logger.warn("Other link types not yet implemented");
1304 // }else{
1305 // logger.warn("Unknown link type or missing ref");
1306 // }
1307 // if (result == null){
1308 // success.setValue(false);
1309 // }
1310 // return result;
1311 // }
1312 //
1313 //
1314 // protected Reference makeAccordingTo(Element elAccordingTo, MapWrapper<Reference> referenceMap, ResultWrapper<Boolean> success){
1315 // Reference result = null;
1316 // if (elAccordingTo != null){
1317 // String childName = "AccordingToDetailed";
1318 // boolean obligatory = false;
1319 // Element elAccordingToDetailed = XmlHelp.getSingleChildElement(success, elAccordingTo, childName, elAccordingTo.getNamespace(), obligatory);
1320 //
1321 // childName = "Simple";
1322 // obligatory = true;
1323 // Element elSimple = XmlHelp.getSingleChildElement(success, elAccordingTo, childName, elAccordingTo.getNamespace(), obligatory);
1324 //
1325 // if (elAccordingToDetailed != null){
1326 // result = makeAccordingToDetailed(elAccordingToDetailed, referenceMap, success);
1327 // }else{
1328 // result = ReferenceFactory.newGeneric();
1329 // String title = elSimple.getTextNormalize();
1330 // result.setTitleCache(title, true);
1331 // }
1332 // }
1333 // return result;
1334 // }
1335 //
1336 //
1337 // private Reference makeAccordingToDetailed(Element elAccordingToDetailed, MapWrapper<Reference> referenceMap, ResultWrapper<Boolean> success){
1338 // Reference result = null;
1339 // Namespace tcsNamespace = elAccordingToDetailed.getNamespace();
1340 // if (elAccordingToDetailed != null){
1341 // //AuthorTeam
1342 // String childName = "AuthorTeam";
1343 // boolean obligatory = false;
1344 // Element elAuthorTeam = XmlHelp.getSingleChildElement(success, elAccordingToDetailed, childName, tcsNamespace, obligatory);
1345 // makeAccordingToAuthorTeam(elAuthorTeam, success);
1346 //
1347 // //PublishedIn
1348 // childName = "PublishedIn";
1349 // obligatory = false;
1350 // Element elPublishedIn = XmlHelp.getSingleChildElement(success, elAccordingToDetailed, childName, tcsNamespace, obligatory);
1351 // result = makeReferenceType(elPublishedIn, Reference.class, referenceMap, success);
1352 //
1353 // //MicroReference
1354 // childName = "MicroReference";
1355 // obligatory = false;
1356 // Element elMicroReference = XmlHelp.getSingleChildElement(success, elAccordingToDetailed, childName, tcsNamespace, obligatory);
1357 // String microReference = elMicroReference.getTextNormalize();
1358 // if (CdmUtils.Nz(microReference).equals("")){
1359 // //TODO
1360 // logger.warn("MicroReference not yet implemented for AccordingToDetailed");
1361 // }
1362 // }
1363 // return result;
1364 // }
1365 //
1366 // private Team makeAccordingToAuthorTeam(Element elAuthorTeam, ResultWrapper<Boolean> succes){
1367 // Team result = null;
1368 // if (elAuthorTeam != null){
1369 // //TODO
1370 // logger.warn("AuthorTeam not yet implemented for AccordingToDetailed");
1371 // }
1372 // return result;
1373 // }
1374
1375
1376
1377 }