rename Reference.authorTeam -> authorship #4432
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / markup / MarkupDocumentImportNoComponent.java
index 9cdede03c560214c457163594f844df3cf6d3d67..ad8dd2f5c602b87a1272eb7583e6580376695ae1 100644 (file)
@@ -11,16 +11,10 @@ package eu.etaxonomy.cdm.io.markup;
 \r
 import java.net.MalformedURLException;\r
 import java.net.URL;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.HashMap;\r
 import java.util.HashSet;\r
-import java.util.List;\r
 import java.util.Map;\r
 import java.util.Set;\r
 import java.util.UUID;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
 \r
 import javax.xml.stream.Location;\r
 import javax.xml.stream.XMLEventReader;\r
@@ -32,14 +26,8 @@ import javax.xml.stream.events.XMLEvent;
 import org.apache.commons.lang.StringUtils;\r
 import org.apache.log4j.Logger;\r
 \r
-import eu.etaxonomy.cdm.common.CdmUtils;\r
 import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;\r
 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;\r
-import eu.etaxonomy.cdm.model.common.AnnotatableEntity;\r
-import eu.etaxonomy.cdm.model.common.Annotation;\r
-import eu.etaxonomy.cdm.model.common.AnnotationType;\r
-import eu.etaxonomy.cdm.model.common.CdmBase;\r
-import eu.etaxonomy.cdm.model.common.Extension;\r
 import eu.etaxonomy.cdm.model.common.ExtensionType;\r
 import eu.etaxonomy.cdm.model.common.Language;\r
 import eu.etaxonomy.cdm.model.common.OriginalSourceType;\r
@@ -50,18 +38,11 @@ import eu.etaxonomy.cdm.model.description.Distribution;
 import eu.etaxonomy.cdm.model.description.Feature;\r
 import eu.etaxonomy.cdm.model.description.PolytomousKey;\r
 import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
-import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;\r
-import eu.etaxonomy.cdm.model.description.PresenceTerm;\r
 import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
 import eu.etaxonomy.cdm.model.description.TextData;\r
-import eu.etaxonomy.cdm.model.location.NamedArea;\r
-import eu.etaxonomy.cdm.model.location.NamedAreaLevel;\r
-import eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity;\r
-import eu.etaxonomy.cdm.model.media.Media;\r
 import eu.etaxonomy.cdm.model.name.CultivarPlantName;\r
 import eu.etaxonomy.cdm.model.name.NonViralName;\r
 import eu.etaxonomy.cdm.model.name.Rank;\r
-import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;\r
 import eu.etaxonomy.cdm.model.reference.Reference;\r
 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;\r
 import eu.etaxonomy.cdm.model.taxon.Classification;\r
@@ -74,19 +55,23 @@ import eu.etaxonomy.cdm.model.taxon.TaxonNode;
  * \r
  */\r
 public class MarkupDocumentImportNoComponent extends MarkupImportBase {\r
+       @SuppressWarnings("unused")\r
        private static final Logger logger = Logger.getLogger(MarkupDocumentImportNoComponent.class);\r
-\r
-\r
+       \r
        private MarkupKeyImport keyImport;\r
+\r
+       private MarkupModsImport modsImport;\r
+       private MarkupFeatureImport featureImport;\r
        private MarkupSpecimenImport specimenImport;\r
-       \r
        private MarkupNomenclatureImport nomenclatureImport;\r
-       \r
+\r
        public MarkupDocumentImportNoComponent(MarkupDocumentImport docImport) {\r
                super(docImport);\r
-               keyImport = new MarkupKeyImport(docImport);\r
-               specimenImport = new MarkupSpecimenImport(docImport);\r
-               nomenclatureImport = new MarkupNomenclatureImport(docImport, keyImport, specimenImport);\r
+               this.keyImport = new MarkupKeyImport(docImport);\r
+               this.specimenImport = new MarkupSpecimenImport(docImport);\r
+               this.nomenclatureImport = new MarkupNomenclatureImport(docImport, specimenImport);\r
+               this.modsImport = new MarkupModsImport(docImport);\r
+               this.featureImport = new MarkupFeatureImport(docImport, specimenImport, nomenclatureImport);\r
        }\r
 \r
        public void doInvoke(MarkupImportState state) throws XMLStreamException { \r
@@ -193,8 +178,8 @@ public class MarkupDocumentImportNoComponent extends MarkupImportBase {
                                        message = String.format(message, baseUrl);\r
                                        fireWarningEvent(message, next, 8);\r
                                }\r
-                       } else if (isStartingElement(next, MODS)){\r
-                               handleNotYetImplementedElement(next);\r
+                       } else if (isStartingElement(next, MODS)){      \r
+                               modsImport.handleMods(state, reader, next);\r
                        } else {\r
                                handleUnexpectedElement(next);\r
                        }\r
@@ -261,6 +246,10 @@ public class MarkupDocumentImportNoComponent extends MarkupImportBase {
                }\r
                Rank thisRank = taxon.getName().getRank();\r
                Rank lastRank = lastTaxon.getName().getRank();\r
+               if (lastRank == null){\r
+                       String message = "Last rank was null. Can't create tree correctly";\r
+                       fireWarningEvent(message, makeLocationStr(dataLocation), 12);\r
+               }\r
                if (lastTaxon.getTaxonNodes().size() > 0) {\r
                        TaxonNode lastNode = lastTaxon.getTaxonNodes().iterator().next();\r
                        if (thisRank == null){\r
@@ -279,7 +268,14 @@ public class MarkupDocumentImportNoComponent extends MarkupImportBase {
                                        tree.addChildTaxon(taxon, null, null);\r
                                }\r
                        } else if (thisRank.isHigher(lastRank)) {\r
-                               doTaxonRelation(state, taxon, lastNode.getParent().getTaxon(),  dataLocation);\r
+                               TaxonNode parent = lastNode.getParent();\r
+                               if (parent != null){\r
+                                       doTaxonRelation(state, taxon, parent.getTaxon(),        dataLocation);\r
+                               }else{\r
+                                       String warning = "No parent available for lastNode. Classification can not be build correctly. Maybe the rank was missing for the lastNode";\r
+                                       fireWarningEvent(warning, makeLocationStr(dataLocation), 16);\r
+                                       //TODO what to do in this case (haven't spend time to think about yet\r
+                               }\r
                                // TaxonNode parentNode = handleTaxonRelation(state, taxon,\r
                                // lastNode.getParent().getTaxon());\r
                                // parentNode.addChildTaxon(taxon, null, null, null);\r
@@ -394,7 +390,7 @@ public class MarkupDocumentImportNoComponent extends MarkupImportBase {
                                        nomenclatureImport.handleNomenclature(state, reader, next);\r
                                        hasNomenclature = true;\r
                                } else if (isStartingElement(next, FEATURE)) {\r
-                                       handleFeature(state, reader, next);\r
+                                       featureImport.handleFeature(state, reader, next);\r
                                } else if (isStartingElement(next, NOTES)) {\r
                                        // TODO is this the correct way to handle notes?\r
                                        String note = handleNotes(state, reader, next);\r
@@ -421,11 +417,11 @@ public class MarkupDocumentImportNoComponent extends MarkupImportBase {
                                                desc.addElement(textData);\r
                                        }\r
                                        textData = (TextData)desc.getElements().iterator().next();\r
-                                       makeFeatureFigureRef(state, reader, desc, false, textData, next);\r
+                                       featureImport.makeFeatureFigureRef(state, reader, desc, false, textData, next);\r
                                } else if (isStartingElement(next, FIGURE)) {\r
-                                       handleFigure(state, reader, next);\r
+                                       handleFigure(state, reader, next, specimenImport, nomenclatureImport);\r
                                } else if (isStartingElement(next, FOOTNOTE)) {\r
-                                       FootnoteDataHolder footnote = handleFootnote(state, reader,     next);\r
+                                       FootnoteDataHolder footnote = handleFootnote(state, reader,     next, specimenImport, nomenclatureImport);\r
                                        if (footnote.isRef()) {\r
                                                String message = "Ref footnote not implemented here";\r
                                                fireWarningEvent(message, next, 4);\r
@@ -454,14 +450,12 @@ public class MarkupDocumentImportNoComponent extends MarkupImportBase {
                WriterDataHolder writer = handleWriter(state, reader, next);\r
                taxon.addExtension(writer.extension);\r
                // TODO what if taxonTitle comes later\r
-               if (StringUtils.isNotBlank(taxonTitle)\r
-                               && writer.extension != null) {\r
+               if (StringUtils.isNotBlank(taxonTitle) && writer.extension != null) {\r
                        Reference<?> sec = ReferenceFactory.newBookSection();\r
                        sec.setTitle(taxonTitle);\r
                        TeamOrPersonBase<?> author = createAuthor(writer.writer);\r
-                       sec.setAuthorTeam(author);\r
-                       sec.setInReference(state.getConfig()\r
-                                       .getSourceReference());\r
+                       sec.setAuthorship(author);\r
+                       sec.setInReference(state.getConfig().getSourceReference());\r
                        taxon.setSec(sec);\r
                        registerFootnotes(state, sec, writer.footnotes);\r
                } else {\r
@@ -641,1306 +635,5 @@ public class MarkupDocumentImportNoComponent extends MarkupImportBase {
 \r
        }\r
 \r
-       private WriterDataHolder handleWriter(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               String text = "";\r
-               checkNoAttributes(parentEvent);\r
-               WriterDataHolder dataHolder = new WriterDataHolder();\r
-               List<FootnoteDataHolder> footnotes = new ArrayList<FootnoteDataHolder>();\r
-\r
-               // TODO handle attributes\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               text = CdmUtils.removeBrackets(text);\r
-                               if (checkMandatoryText(text, parentEvent)) {\r
-                                       text = normalize(text);\r
-                                       dataHolder.writer = text;\r
-                                       dataHolder.footnotes = footnotes;\r
-\r
-                                       // Extension\r
-                                       UUID uuidWriterExtension = MarkupTransformer.uuidWriterExtension;\r
-                                       ExtensionType writerExtensionType = this\r
-                                                       .getExtensionType(state, uuidWriterExtension,\r
-                                                                       "Writer", "writer", "writer");\r
-                                       Extension extension = Extension.NewInstance();\r
-                                       extension.setType(writerExtensionType);\r
-                                       extension.setValue(text);\r
-                                       dataHolder.extension = extension;\r
-\r
-                                       // Annotation\r
-                                       UUID uuidWriterAnnotation = MarkupTransformer.uuidWriterAnnotation;\r
-                                       AnnotationType writerAnnotationType = this.getAnnotationType(state, uuidWriterAnnotation, "Writer", "writer", "writer", null);\r
-                                       Annotation annotation = Annotation.NewInstance(text, writerAnnotationType, getDefaultLanguage(state));\r
-                                       dataHolder.annotation = annotation;\r
-\r
-                                       return dataHolder;\r
-                               } else {\r
-                                       return null;\r
-                               }\r
-                       } else if (isStartingElement(next, FOOTNOTE_REF)) {\r
-                               FootnoteDataHolder footNote = handleFootnoteRef(state, reader, next);\r
-                               if (footNote.isRef()) {\r
-                                       footnotes.add(footNote);\r
-                               } else {\r
-                                       logger.warn("Non ref footnotes not yet impelemnted");\r
-                               }\r
-                       } else if (next.isCharacters()) {\r
-                               text += next.asCharacters().getData();\r
-\r
-                       } else {\r
-                               handleUnexpectedElement(next);\r
-                               state.setUnsuccessfull();\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<writer> has no end tag");\r
-       }\r
-\r
-       private void registerFootnotes(MarkupImportState state, AnnotatableEntity entity, List<FootnoteDataHolder> footnotes) {\r
-               for (FootnoteDataHolder footNote : footnotes) {\r
-                       registerFootnoteDemand(state, entity, footNote);\r
-               }\r
-       }\r
-\r
-       private void registerGivenFootnote(MarkupImportState state, FootnoteDataHolder footnote) {\r
-               state.registerFootnote(footnote);\r
-               Set<AnnotatableEntity> demands = state.getFootnoteDemands(footnote.id);\r
-               if (demands != null) {\r
-                       for (AnnotatableEntity entity : demands) {\r
-                               attachFootnote(state, entity, footnote);\r
-                       }\r
-               }\r
-       }\r
-\r
-       private void registerGivenFigure(MarkupImportState state, XMLEvent next, String id, Media figure) {\r
-               state.registerFigure(id, figure);\r
-               Set<AnnotatableEntity> demands = state.getFigureDemands(id);\r
-               if (demands != null) {\r
-                       for (AnnotatableEntity entity : demands) {\r
-                               attachFigure(state, next, entity, figure);\r
-                       }\r
-               }\r
-               save(figure, state);\r
-       }\r
-\r
-       private void registerFootnoteDemand(MarkupImportState state, AnnotatableEntity entity, FootnoteDataHolder footnote) {\r
-               FootnoteDataHolder existingFootnote = state.getFootnote(footnote.ref);\r
-               if (existingFootnote != null) {\r
-                       attachFootnote(state, entity, existingFootnote);\r
-               } else {\r
-                       Set<AnnotatableEntity> demands = state.getFootnoteDemands(footnote.ref);\r
-                       if (demands == null) {\r
-                               demands = new HashSet<AnnotatableEntity>();\r
-                               state.putFootnoteDemands(footnote.ref, demands);\r
-                       }\r
-                       demands.add(entity);\r
-               }\r
-       }\r
-\r
-       private void registerFigureDemand(MarkupImportState state, XMLEvent next, AnnotatableEntity entity, String figureRef) {\r
-               Media existingFigure = state.getFigure(figureRef);\r
-               if (existingFigure != null) {\r
-                       attachFigure(state, next, entity, existingFigure);\r
-               } else {\r
-                       Set<AnnotatableEntity> demands = state.getFigureDemands(figureRef);\r
-                       if (demands == null) {\r
-                               demands = new HashSet<AnnotatableEntity>();\r
-                               state.putFigureDemands(figureRef, demands);\r
-                       }\r
-                       demands.add(entity);\r
-               }\r
-       }\r
-\r
-       private void attachFootnote(MarkupImportState state, AnnotatableEntity entity, FootnoteDataHolder footnote) {\r
-               AnnotationType annotationType = this.getAnnotationType(state, MarkupTransformer.uuidFootnote, "Footnote", "An e-flora footnote", "fn", null);\r
-               Annotation annotation = Annotation.NewInstance(footnote.string, annotationType, getDefaultLanguage(state));\r
-               // TODO transient objects\r
-               entity.addAnnotation(annotation);\r
-               save(entity, state);\r
-       }\r
-\r
-       private void attachFigure(MarkupImportState state, XMLEvent next, AnnotatableEntity entity, Media figure) {\r
-               // IdentifiableEntity<?> toSave;\r
-               if (entity.isInstanceOf(TextData.class)) {\r
-                       TextData deb = CdmBase.deproxy(entity, TextData.class);\r
-                       deb.addMedia(figure);\r
-                       // toSave = ((TaxonDescription)deb.getInDescription()).getTaxon();\r
-               } else if (entity.isInstanceOf(SpecimenOrObservationBase.class)) {\r
-                       String message = "figures for specimen should be handled as Textdata";\r
-                       fireWarningEvent(message, next, 4);\r
-                       // toSave = ime;\r
-               } else if (entity.isInstanceOf(IdentifiableMediaEntity.class)) {\r
-                       IdentifiableMediaEntity<?> ime = CdmBase.deproxy(entity, IdentifiableMediaEntity.class);\r
-                       ime.addMedia(figure);\r
-                       // toSave = ime;\r
-               } else {\r
-                       String message = "Unsupported entity to attach media: %s";\r
-                       message = String.format(message, entity.getClass().getName());\r
-                       // toSave = null;\r
-               }\r
-               save(entity, state);\r
-       }\r
-\r
-       private Media handleFigure(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               // FigureDataHolder result = new FigureDataHolder();\r
-\r
-               Map<String, Attribute> attributes = getAttributes(parentEvent);\r
-               String id = getAndRemoveAttributeValue(attributes, ID);\r
-               String type = getAndRemoveAttributeValue(attributes, TYPE);\r
-               String urlAttr = getAndRemoveAttributeValue(attributes, URL);\r
-               checkNoAttributes(attributes, parentEvent);\r
-\r
-               String urlString = null;\r
-               String legendString = null;\r
-               String titleString = null;\r
-               String numString = null;\r
-               String text = null;\r
-               if (isNotBlank(urlAttr)){\r
-                       urlString = CdmUtils.Nz(state.getBaseMediaUrl()) + urlAttr;\r
-               }\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               if (isNotBlank(text)){\r
-                                       fireWarningEvent("Text not yet handled for figures: " + text, next, 4);\r
-                               }\r
-                               Media media = makeFigure(state, id, type, urlString, legendString, titleString, numString, next);\r
-                               return media;\r
-                       } else if (isStartingElement(next, FIGURE_LEGEND)) {\r
-                               // TODO same as figure string ?\r
-                               legendString = handleFootnoteString(state, reader, next);\r
-                       } else if (isStartingElement(next, FIGURE_TITLE)) {\r
-                               titleString = getCData(state, reader, next);\r
-                       } else if (isStartingElement(next, URL)) {\r
-                               String localUrl = getCData(state, reader, next);\r
-                               String url = CdmUtils.Nz(state.getBaseMediaUrl()) + localUrl;\r
-                               if (isBlank(urlString)){\r
-                                       urlString = url;\r
-                               }\r
-                               if (! url.equals(urlString)){\r
-                                       String message = "URL attribute and URL element differ. Attribute: %s, Element: %s";\r
-                                       fireWarningEvent(String.format(message, urlString, url), next, 2);\r
-                               }\r
-                       } else if (isStartingElement(next, NUM)) {\r
-                               numString = getCData(state, reader, next);\r
-                       } else if (next.isCharacters()) {\r
-                               text += CdmUtils.concat("", text, next.asCharacters().getData());\r
-                       } else {\r
-                               fireUnexpectedEvent(next, 0);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<figure> has no end tag");\r
-       }\r
-\r
-       /**\r
-        * @param state\r
-        * @param id\r
-        * @param type\r
-        * @param urlString\r
-        * @param legendString\r
-        * @param titleString\r
-        * @param numString\r
-        * @param next\r
-        */\r
-       private Media makeFigure(MarkupImportState state, String id, String type, String urlString, \r
-                       String legendString, String titleString, String numString, XMLEvent next) {\r
-               Media media = null;\r
-               boolean isFigure = false;\r
-               try {\r
-                       //TODO maybe everything is a figure as it is all taken from a book\r
-                       if ("lineart".equals(type)) {\r
-                               isFigure = true;\r
-//                             media = Figure.NewInstance(url.toURI(), null, null,     null);\r
-                       } else if (type == null || "photo".equals(type)\r
-                                       || "signature".equals(type)\r
-                                       || "others".equals(type)) {\r
-                               //TODO\r
-                       } else {\r
-                               String message = "Unknown figure type '%s'";\r
-                               message = String.format(message, type);\r
-                               fireWarningEvent(message, next, 2);\r
-                       }\r
-                       media = docImport.getImageMedia(urlString, docImport.getReadMediaData(), isFigure);\r
-                       \r
-                       if (media != null){\r
-                               // title\r
-                               if (StringUtils.isNotBlank(titleString)) {\r
-                                       media.putTitle(getDefaultLanguage(state), titleString);\r
-                               }\r
-                               // legend\r
-                               if (StringUtils.isNotBlank(legendString)) {\r
-                                       media.putDescription(getDefaultLanguage(state), legendString);\r
-                               }\r
-                               if (StringUtils.isNotBlank(numString)) {\r
-                                       // TODO use concrete source (e.g. DAPHNIPHYLLACEAE in FM\r
-                                       // vol.13)\r
-                                       Reference<?> citation = state.getConfig().getSourceReference();\r
-                                       media.addImportSource(  numString, "num", citation, null);\r
-                                       // TODO name used in source if available\r
-                               }\r
-                               // TODO which citation\r
-                               if (StringUtils.isNotBlank(id)) {\r
-                                       media.addImportSource(id, null, state.getConfig().getSourceReference(), null);\r
-                               } else {\r
-                                       String message = "Figure id should never be empty or null";\r
-                                       fireWarningEvent(message, next, 6);\r
-                               }\r
-\r
-                               // text\r
-                               // do nothing\r
-                               registerGivenFigure(state, next, id, media);\r
-                               \r
-                       }else{\r
-                               String message = "No media found: ";\r
-                               fireWarningEvent(message, next, 4);\r
-                       }\r
-               } catch (MalformedURLException e) {\r
-                       String message = "Media uri has incorrect syntax: %s";\r
-                       message = String.format(message, urlString);\r
-                       fireWarningEvent(message, next, 4);\r
-//             } catch (URISyntaxException e) {\r
-//                     String message = "Media uri has incorrect syntax: %s";\r
-//                     message = String.format(message, urlString);\r
-//                     fireWarningEvent(message, next, 4);\r
-               }\r
-\r
-               return media;\r
-       }\r
-\r
-       private FigureDataHolder handleFigureRef(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent)\r
-                       throws XMLStreamException {\r
-               FigureDataHolder result = new FigureDataHolder();\r
-               Map<String, Attribute> attributes = getAttributes(parentEvent);\r
-               result.ref = getAndRemoveAttributeValue(attributes, REF);\r
-               checkNoAttributes(attributes, parentEvent);\r
-\r
-               // text is not handled, needed only for debugging purposes\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               return result;\r
-                       } else if (isStartingElement(next, NUM)) {\r
-                               String num = getCData(state, reader, next);\r
-                               result.num = num; // num is not handled during import\r
-                       } else if (isStartingElement(next, FIGURE_PART)) {\r
-                               result.figurePart = getCData(state, reader, next);\r
-                       } else if (next.isCharacters()) {\r
-                               text += next.asCharacters().getData();\r
-                       } else {\r
-                               fireUnexpectedEvent(next, 0);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<figureRef> has no end tag");\r
-       }\r
-\r
-       private FootnoteDataHolder handleFootnote(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               FootnoteDataHolder result = new FootnoteDataHolder();\r
-               Map<String, Attribute> attributes = getAttributes(parentEvent);\r
-               result.id = getAndRemoveAttributeValue(attributes, ID);\r
-               // result.ref = getAndRemoveAttributeValue(attributes, REF);\r
-               checkNoAttributes(attributes, parentEvent);\r
-\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isStartingElement(next, FOOTNOTE_STRING)) {\r
-                               String string = handleFootnoteString(state, reader, next);\r
-                               result.string = string;\r
-                       } else if (isMyEndingElement(next, parentEvent)) {\r
-                               return result;\r
-                       } else {\r
-                               fireUnexpectedEvent(next, 0);\r
-                       }\r
-               }\r
-               return result;\r
-       }\r
-\r
-       private FootnoteDataHolder handleFootnoteRef(MarkupImportState state,\r
-                       XMLEventReader reader, XMLEvent parentEvent)\r
-                       throws XMLStreamException {\r
-               FootnoteDataHolder result = new FootnoteDataHolder();\r
-               Map<String, Attribute> attributes = getAttributes(parentEvent);\r
-               result.ref = getAndRemoveAttributeValue(attributes, REF);\r
-               checkNoAttributes(attributes, parentEvent);\r
-\r
-               // text is not handled, needed only for debugging purposes\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       // if (isStartingElement(next, FOOTNOTE_STRING)){\r
-                       // String string = handleFootnoteString(state, reader, next);\r
-                       // result.string = string;\r
-                       // }else\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               return result;\r
-                       } else if (next.isCharacters()) {\r
-                               text += next.asCharacters().getData();\r
-\r
-                       } else {\r
-                               fireUnexpectedEvent(next, 0);\r
-                       }\r
-               }\r
-               return result;\r
-       }\r
-\r
-\r
-\r
-       private String handleFootnoteString(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               boolean isTextMode = true;\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               return text;\r
-                       } else if (next.isEndElement()) {\r
-                               if (isEndingElement(next, FULL_NAME)) {\r
-                                       popUnimplemented(next.asEndElement());\r
-                               } else if (isEndingElement(next, BR)) {\r
-                                       isTextMode = true;\r
-                               } else if (isHtml(next)) {\r
-                                       text += getXmlTag(next);\r
-                               } else {\r
-                                       handleUnexpectedEndElement(next.asEndElement());\r
-                               }\r
-                       } else if (next.isStartElement()) {\r
-                               if (isStartingElement(next, FULL_NAME)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, GATHERING)) {\r
-                                       text += specimenImport.handleInLineGathering(state, reader, next);\r
-                               } else if (isStartingElement(next, REFERENCES)) {\r
-                                       text += " " + handleInLineReferences(state, reader, next)+ " ";\r
-                               } else if (isStartingElement(next, BR)) {\r
-                                       text += "<br/>";\r
-                                       isTextMode = false;\r
-                               } else if (isStartingElement(next, NOMENCLATURE)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isHtml(next)) {\r
-                                       text += getXmlTag(next);\r
-                               } else {\r
-                                       handleUnexpectedStartElement(next.asStartElement());\r
-                               }\r
-                       } else if (next.isCharacters()) {\r
-                               if (!isTextMode) {\r
-                                       String message = "footnoteString is not in text mode";\r
-                                       fireWarningEvent(message, next, 6);\r
-                               } else {\r
-                                       text += next.asCharacters().getData().trim(); \r
-                                       // getCData(state, reader, next); does not work as we have inner tags like <references>\r
-                               }\r
-                       } else {\r
-                               handleUnexpectedEndElement(next.asEndElement());\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<footnoteString> has no closing tag");\r
-\r
-       }\r
-\r
-       private String handleInLineReferences(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               checkNoAttributes(parentEvent);\r
-\r
-               boolean hasReference = false;\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               checkMandatoryElement(hasReference, parentEvent.asStartElement(), REFERENCE);\r
-                               return text;\r
-                       } else if (isStartingElement(next, REFERENCE)) {\r
-                               text += handleInLineReference(state, reader, next);\r
-                               hasReference = true;\r
-                       } else {\r
-                               handleUnexpectedElement(next);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<References> has no closing tag");\r
-       }\r
-\r
-       private String handleInLineReference(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent)throws XMLStreamException {\r
-               Reference<?> reference = nomenclatureImport.handleReference(state, reader, parentEvent);\r
-               String result = "<cdm:ref uuid='%s'>%s</ref>";\r
-               result = String.format(result, reference.getUuid(), reference.getTitleCache());\r
-               save(reference, state);\r
-               return result;\r
-       }\r
-\r
-\r
-       private void handleFeature(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               Map<String, Attribute> attrs = getAttributes(parentEvent);\r
-               Boolean isFreetext = getAndRemoveBooleanAttributeValue(parentEvent, attrs, IS_FREETEXT, false);\r
-               String classValue =getAndRemoveRequiredAttributeValue(parentEvent, attrs, CLASS);\r
-               checkNoAttributes(attrs, parentEvent);\r
-               \r
-               \r
-               Feature feature = makeFeature(classValue, state, parentEvent, null);\r
-               Taxon taxon = state.getCurrentTaxon();\r
-               TaxonDescription taxonDescription = getTaxonDescription(taxon, state.getConfig().getSourceReference(), NO_IMAGE_GALLERY, CREATE_NEW);\r
-               // TextData figureHolderTextData = null; //for use with one TextData for\r
-               // all figure only\r
-\r
-               boolean isDescription = feature.equals(Feature.DESCRIPTION());\r
-               DescriptionElementBase lastDescriptionElement = null;\r
-               \r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               state.putFeatureToGeneralSorterList(feature);\r
-                               return;\r
-                       } else if (isEndingElement(next, DISTRIBUTION_LIST) || isEndingElement(next, HABITAT_LIST)) { \r
-                               // only handle list elements\r
-                       } else if (isStartingElement(next, HEADING)) {\r
-                               makeFeatureHeading(state, reader, classValue, feature, next);\r
-                       } else if (isStartingElement(next, WRITER)) {\r
-                               makeFeatureWriter(state, reader, feature, taxon, next);\r
-//                     } else if (isStartingElement(next, DISTRIBUTION_LOCALITY)) {\r
-//                             if (!feature.equals(Feature.DISTRIBUTION())) {\r
-//                                     String message = "Distribution locality only allowed for feature of type 'distribution'";\r
-//                                     fireWarningEvent(message, next, 4);\r
-//                             }\r
-//                             handleDistributionLocality(state, reader, next);\r
-                       } else if (isStartingElement(next, DISTRIBUTION_LIST) || isStartingElement(next, HABITAT_LIST)) {\r
-                               // only handle single list elements\r
-                       } else if (isStartingElement(next, HABITAT)) {\r
-                               if (!(feature.equals(Feature.HABITAT())\r
-                                               || feature.equals(Feature.HABITAT_ECOLOGY()) \r
-                                               || feature.equals(Feature.ECOLOGY()))) {\r
-                                       String message = "Habitat only allowed for feature of type 'habitat','habitat ecology' or 'ecology'";\r
-                                       fireWarningEvent(message, next, 4);\r
-                               }\r
-                               handleHabitat(state, reader, next);\r
-                       } else if (isStartingElement(next, CHAR)) {\r
-                               List<TextData> textDataList = handleChar(state, reader, next, null);\r
-                               for (TextData textData : textDataList){\r
-                                       taxonDescription.addElement(textData);\r
-                               }\r
-                       } else if (isStartingElement(next, STRING)) {\r
-                               lastDescriptionElement = makeFeatureString(state, reader,feature, taxonDescription, lastDescriptionElement,next, isFreetext);\r
-                       } else if (isStartingElement(next, FIGURE_REF)) {\r
-                               lastDescriptionElement = makeFeatureFigureRef(state, reader, taxonDescription, isDescription, lastDescriptionElement, next);\r
-                       } else if (isStartingElement(next, REFERENCES)) {\r
-                               // TODO details/microcitation ??\r
-\r
-                               List<Reference<?>> refs = handleReferences(state, reader, next);\r
-                               if (!refs.isEmpty()) {\r
-                                       // TODO\r
-                                       Reference<?> descriptionRef = state.getConfig().getSourceReference();\r
-                                       TaxonDescription description = getTaxonDescription(taxon, descriptionRef, false, true);\r
-                                       TextData featurePlaceholder = docImport.getFeaturePlaceholder(state, description, feature, true);\r
-                                       for (Reference<?> citation : refs) {\r
-                                               featurePlaceholder.addSource(OriginalSourceType.PrimaryTaxonomicSource,\r
-                                                               null, null, citation, null);\r
-                                       }\r
-                               } else {\r
-                                       String message = "No reference found in references";\r
-                                       fireWarningEvent(message, next, 6);\r
-                               }\r
-                       } else if (isStartingElement(next, NUM)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, NUM)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else {\r
-                               handleUnexpectedElement(next);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<Feature> has no closing tag");\r
-       }\r
-\r
-       /**\r
-        * @param state\r
-        * @param reader\r
-        * @param taxonDescription\r
-        * @param isDescription\r
-        * @param lastDescriptionElement\r
-        * @param next\r
-        * @return\r
-        * @throws XMLStreamException\r
-        */\r
-       private DescriptionElementBase makeFeatureFigureRef(MarkupImportState state, XMLEventReader reader,TaxonDescription taxonDescription, \r
-                                       boolean isDescription, DescriptionElementBase lastDescriptionElement, XMLEvent next) throws XMLStreamException {\r
-               FigureDataHolder figureHolder = handleFigureRef(state, reader, next);\r
-               Feature figureFeature = getFeature(state, MarkupTransformer.uuidFigures, "Figures", "Figures", "Fig.",null);\r
-               if (isDescription) {\r
-                       TextData figureHolderTextData = null;\r
-                       // if (figureHolderTextData == null){\r
-                       figureHolderTextData = TextData.NewInstance(figureFeature);\r
-                       if (StringUtils.isNotBlank(figureHolder.num)) {\r
-                               String annotationText = "<num>" + figureHolder.num.trim() + "</num>";\r
-                               Annotation annotation = Annotation.NewInstance(annotationText, AnnotationType.TECHNICAL(), getDefaultLanguage(state));\r
-                               figureHolderTextData.addAnnotation(annotation);\r
-                       }\r
-                       if (StringUtils.isNotBlank(figureHolder.figurePart)) {\r
-                               String annotationText = "<figurePart>"+ figureHolder.figurePart.trim() + "</figurePart>";\r
-                               Annotation annotation = Annotation.NewInstance(annotationText,AnnotationType.EDITORIAL(), getDefaultLanguage(state));\r
-                               figureHolderTextData.addAnnotation(annotation);\r
-                       }\r
-                       // if (StringUtils.isNotBlank(figureText)){\r
-                       // figureHolderTextData.putText(language, figureText);\r
-                       // }\r
-                       taxonDescription.addElement(figureHolderTextData);\r
-                       // }\r
-                       registerFigureDemand(state, next, figureHolderTextData, figureHolder.ref);\r
-               } else {\r
-                       if (lastDescriptionElement == null) {\r
-                               String message = "No description element created yet that can be referred by figure. Create new TextData instead";\r
-                               fireWarningEvent(message, next, 4);\r
-                               lastDescriptionElement = TextData.NewInstance(figureFeature);\r
-                               taxonDescription.addElement(lastDescriptionElement);\r
-                       }\r
-                       registerFigureDemand(state, next, lastDescriptionElement,       figureHolder.ref);\r
-               }\r
-               return lastDescriptionElement;\r
-       }\r
-\r
-       /**\r
-        * @param state\r
-        * @param reader\r
-        * @param feature\r
-        * @param taxonDescription\r
-        * @param lastDescriptionElement\r
-        * @param distributionList \r
-        * @param next\r
-        * @return\r
-        * @throws XMLStreamException\r
-        */\r
-       private DescriptionElementBase makeFeatureString(MarkupImportState state,XMLEventReader reader, Feature feature, \r
-                               TaxonDescription taxonDescription, DescriptionElementBase lastDescriptionElement, XMLEvent next, Boolean isFreetext) throws XMLStreamException {\r
-               \r
-               //for specimen only\r
-               if (feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.MATERIALS_EXAMINED())){\r
-                       \r
-                       \r
-                       List<DescriptionElementBase> specimens = specimenImport.handleMaterialsExamined(state, reader, next, feature);\r
-                       for (DescriptionElementBase specimen : specimens){\r
-                               taxonDescription.addElement(specimen);\r
-                               lastDescriptionElement = specimen;\r
-                       }\r
-                       state.setCurrentCollector(null);\r
-                       \r
-                       return lastDescriptionElement;\r
-               }else{\r
-               \r
-                       //others\r
-                       Map<String, String> subheadingMap = handleString(state, reader, next, feature);\r
-                       for (String subheading : subheadingMap.keySet()) {\r
-                               Feature subheadingFeature = feature;\r
-                               if (StringUtils.isNotBlank(subheading) && subheadingMap.size() > 1) {\r
-                                       subheadingFeature = makeFeature(subheading, state, next, null);\r
-                               }\r
-                               if (feature.equals(Feature.COMMON_NAME()) && (isFreetext == null || !isFreetext)){\r
-                                       List<DescriptionElementBase> commonNames = makeVernacular(state, subheading, subheadingMap.get(subheading));\r
-                                       for (DescriptionElementBase commonName : commonNames){\r
-                                               taxonDescription.addElement(commonName);\r
-                                               lastDescriptionElement = commonName;\r
-                                       }\r
-                               }else {\r
-                                       TextData textData = TextData.NewInstance(subheadingFeature);\r
-                                       textData.putText(getDefaultLanguage(state), subheadingMap.get(subheading));\r
-                                       taxonDescription.addElement(textData);\r
-                                       lastDescriptionElement = textData;\r
-                                       // TODO how to handle figures when these data are split in\r
-                                       // subheadings\r
-                               }\r
-                       }\r
-                       return lastDescriptionElement;\r
-               }\r
-       }\r
-\r
-       private List<DescriptionElementBase> makeVernacular(MarkupImportState state, String subheading, String commonNameString) throws XMLStreamException {\r
-               List<DescriptionElementBase> result = new ArrayList<DescriptionElementBase>();\r
-               String[] splits = commonNameString.split(",");\r
-               for (String split : splits){\r
-                       split = split.trim();\r
-                       if (! split.matches(".*\\(.*\\)\\.?")){\r
-                               fireWarningEvent("Common name string '"+split+"' does not match given pattern", state.getReader().peek(), 4);\r
-                       }\r
-                       \r
-                       String name = split.replaceAll("\\(.*\\)", "").replace(".", "").trim();\r
-                       String languageStr = split.replaceFirst(".*\\(", "").replaceAll("\\)\\.?", "").trim();\r
-                       \r
-                       Language language = null;\r
-                       if (StringUtils.isNotBlank(languageStr)){\r
-                               try {\r
-                                       UUID langUuid = state.getTransformer().getLanguageUuid(languageStr);\r
-                                       TermVocabulary<?> voc = null;\r
-                                       language = getLanguage(state, langUuid, languageStr, languageStr, null, voc);\r
-                                       if (language == null){\r
-                                               logger.warn("Language " + languageStr + " not recognized by transformer");\r
-                                       }\r
-                               } catch (UndefinedTransformerMethodException e) {\r
-                                       throw new RuntimeException(e);\r
-                               }\r
-                       }\r
-                       NamedArea area = null;\r
-                       CommonTaxonName commonTaxonName = CommonTaxonName.NewInstance(name, language, area);\r
-                       result.add(commonTaxonName);\r
-               }\r
-               \r
-               return result;\r
-       }\r
-\r
-       /**\r
-        * @param state\r
-        * @param reader\r
-        * @param feature\r
-        * @param taxon\r
-        * @param next\r
-        * @throws XMLStreamException\r
-        */\r
-       private void makeFeatureWriter(MarkupImportState state,XMLEventReader reader, Feature feature, Taxon taxon, XMLEvent next) throws XMLStreamException {\r
-               WriterDataHolder writer = handleWriter(state, reader, next);\r
-               if (isNotBlank(writer.writer)) {\r
-                       // TODO\r
-                       Reference<?> ref = state.getConfig().getSourceReference();\r
-                       TaxonDescription description = getTaxonDescription(taxon, ref,\r
-                                       false, true);\r
-                       TextData featurePlaceholder = docImport.getFeaturePlaceholder(state,\r
-                                       description, feature, true);\r
-                       featurePlaceholder.addAnnotation(writer.annotation);\r
-                       registerFootnotes(state, featurePlaceholder, writer.footnotes);\r
-               } else {\r
-                       String message = "Writer element is empty";\r
-                       fireWarningEvent(message, next, 4);\r
-               }\r
-       }\r
-\r
-       /**\r
-        * @param state\r
-        * @param reader\r
-        * @param classValue\r
-        * @param feature\r
-        * @param next\r
-        * @throws XMLStreamException\r
-        */\r
-       private void makeFeatureHeading(MarkupImportState state, XMLEventReader reader, String classValue, Feature feature, XMLEvent next) throws XMLStreamException {\r
-               String heading = handleHeading(state, reader, next);\r
-               if (StringUtils.isNotBlank(heading)) {\r
-                       if (!heading.equalsIgnoreCase(classValue)) {\r
-                               try {\r
-                                       if (!feature.equals(state.getTransformer().getFeatureByKey(\r
-                                                       heading))) {\r
-                                               UUID headerFeatureUuid = state.getTransformer()\r
-                                                               .getFeatureUuid(heading);\r
-                                               if (!feature.getUuid().equals(headerFeatureUuid)) {\r
-                                                       String message = "Feature heading '%s' differs from feature class '%s' and can not be transformed to feature";\r
-                                                       message = String.format(message, heading,\r
-                                                                       classValue);\r
-                                                       fireWarningEvent(message, next, 1);\r
-                                               }\r
-                                       }\r
-                               } catch (UndefinedTransformerMethodException e) {\r
-                                       throw new RuntimeException(e);\r
-                               }\r
-                       } else {\r
-                               // do nothing\r
-                       }\r
-               }\r
-       }\r
-\r
-       private List<Reference<?>> handleReferences(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               // attributes\r
-               Map<String, Attribute> attributes = getAttributes(parentEvent);\r
-               String bibliography = getAndRemoveAttributeValue(attributes,\r
-                               BIBLIOGRAPHY);\r
-               String serialsAbbreviations = getAndRemoveAttributeValue(attributes,\r
-                               SERIALS_ABBREVIATIONS);\r
-               if (isNotBlank(bibliography) || isNotBlank(serialsAbbreviations)) {\r
-                       String message = "Attributes not yet implemented for <references>";\r
-                       fireWarningEvent(message, parentEvent, 4);\r
-               }\r
-\r
-               List<Reference<?>> result = new ArrayList<Reference<?>>();\r
-\r
-               // elements\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (next.isEndElement()) {\r
-                               if (isMyEndingElement(next, parentEvent)) {\r
-                                       return result;\r
-                               } else {\r
-                                       if (isEndingElement(next, HEADING)) {\r
-                                               // NOT YET IMPLEMENTED\r
-                                               popUnimplemented(next.asEndElement());\r
-                                       } else if (isEndingElement(next, WRITER)) {\r
-                                               // NOT YET IMPLEMENTED\r
-                                               popUnimplemented(next.asEndElement());\r
-                                       } else if (isEndingElement(next, FOOTNOTE)) {\r
-                                               // NOT YET IMPLEMENTED\r
-                                               popUnimplemented(next.asEndElement());\r
-                                       } else if (isEndingElement(next, STRING)) {\r
-                                               // NOT YET IMPLEMENTED\r
-                                               popUnimplemented(next.asEndElement());\r
-                                       } else if (isEndingElement(next, REF_NUM)) {\r
-                                               // NOT YET IMPLEMENTED\r
-                                               popUnimplemented(next.asEndElement());\r
-                                       } else {\r
-                                               handleUnexpectedEndElement(next.asEndElement());\r
-                                       }\r
-                               }\r
-                       } else if (next.isStartElement()) {\r
-                               if (isStartingElement(next, HEADING)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, SUB_HEADING)) {\r
-                                       String subheading = getCData(state, reader, next).trim();\r
-                                       String excludePattern = "(i?)(References?|Literature):?";\r
-                                       if (!subheading.matches(excludePattern)) {\r
-                                               fireNotYetImplementedElement(next.getLocation(), next.asStartElement().getName(), 0);\r
-                                       }\r
-                               } else if (isStartingElement(next, WRITER)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, FOOTNOTE)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, STRING)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, REF_NUM)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, REFERENCE)) {\r
-                                       Reference<?> ref = nomenclatureImport.handleReference(state, reader, next);\r
-                                       result.add(ref);\r
-                               } else {\r
-                                       handleUnexpectedStartElement(next);\r
-                               }\r
-                       } else {\r
-                               handleUnexpectedElement(next);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<References> has no closing tag");\r
-       }\r
-\r
-       private void handleHabitat(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               checkNoAttributes(parentEvent);\r
-               Taxon taxon = state.getCurrentTaxon();\r
-               // TODO which ref to take?\r
-               Reference<?> ref = state.getConfig().getSourceReference();\r
-\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               TaxonDescription description = getTaxonDescription(taxon, ref,\r
-                                               false, true);\r
-                               UUID uuidExtractedHabitat = MarkupTransformer.uuidExtractedHabitat;\r
-                               Feature feature = getFeature(\r
-                                               state,\r
-                                               uuidExtractedHabitat,\r
-                                               "Extracted Habitat",\r
-                                               "An structured habitat that was extracted from a habitat text",\r
-                                               "extr. habit.", null);\r
-                               TextData habitat = TextData.NewInstance(feature);\r
-                               habitat.putText(getDefaultLanguage(state), text);\r
-                               description.addElement(habitat);\r
-\r
-                               return;\r
-                       } else if (next.isStartElement()) {\r
-                               if (isStartingElement(next, ALTITUDE)) {\r
-                                       text = text.trim() + getTaggedCData(state, reader, next);\r
-                               } else if (isStartingElement(next, LIFE_CYCLE_PERIODS)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else {\r
-                                       handleUnexpectedStartElement(next.asStartElement());\r
-                               }\r
-                       } else if (next.isCharacters()) {\r
-                               text += next.asCharacters().getData();\r
-                       } else {\r
-                               handleUnexpectedElement(next);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<Habitat> has no closing tag");\r
-       }\r
-\r
-       private String getTaggedCData(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent) throws XMLStreamException {\r
-               checkNoAttributes(parentEvent);\r
-\r
-               String text = getXmlTag(parentEvent);\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               text += getXmlTag(next);\r
-                               return text;\r
-                       } else if (next.isStartElement()) {\r
-                               text += getTaggedCData(state, reader, next);\r
-                       } else if (next.isEndElement()) {\r
-                               text += getTaggedCData(state, reader, next);\r
-                       } else if (next.isCharacters()) {\r
-                               text += next.asCharacters().getData();\r
-                       } else {\r
-                               handleUnexpectedEndElement(next.asEndElement());\r
-                       }\r
-               }\r
-               throw new IllegalStateException("Some tag has no closing tag");\r
-       }\r
-\r
-       private String handleDistributionLocality(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent)throws XMLStreamException {\r
-               Map<String, Attribute> attributes = getAttributes(parentEvent);\r
-               String classValue = getAndRemoveRequiredAttributeValue(parentEvent, attributes, CLASS);\r
-               String statusValue =getAndRemoveAttributeValue(attributes, STATUS);\r
-               String frequencyValue =getAndRemoveAttributeValue(attributes, FREQUENCY);\r
-               \r
-\r
-               Taxon taxon = state.getCurrentTaxon();\r
-               // TODO which ref to take?\r
-               Reference<?> ref = state.getConfig().getSourceReference();\r
-\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               if (StringUtils.isNotBlank(text)) {\r
-                                       String label = CdmUtils.removeTrailingDot(normalize(text));\r
-                                       TaxonDescription description = getTaxonDescription(taxon, ref, false, true);\r
-                                       NamedAreaLevel level = makeNamedAreaLevel(state,classValue, next);\r
-                                       \r
-                                       //status\r
-                                       PresenceAbsenceTermBase<?> status = null;\r
-                                       if (isNotBlank(statusValue)){\r
-                                               try {\r
-                                                       status = state.getTransformer().getPresenceTermByKey(statusValue);\r
-                                                       if (status == null){\r
-                                                               //TODO\r
-                                                               String message = "The presence/absence status '%s' could not be transformed to an CDM status";                                                          \r
-                                                               fireWarningEvent(String.format(message, statusValue), next, 4);\r
-                                                       }\r
-                                               } catch (UndefinedTransformerMethodException e) {\r
-                                                       throw new RuntimeException(e);\r
-                                               }\r
-                                       }else{\r
-                                               status = PresenceTerm.PRESENT();\r
-                                       }\r
-                                       //frequency\r
-                                       if (isNotBlank(frequencyValue)){\r
-                                               String message = "The frequency attribute is currently not yet available in CDM";\r
-                                               fireWarningEvent(message, parentEvent, 6);\r
-                                       }\r
-                                       \r
-                                       NamedArea higherArea = null;\r
-                                       List<NamedArea> areas = new ArrayList<NamedArea>(); \r
-                                       \r
-                                       String patSingleArea = "([^,\\(]{3,})";\r
-                                       String patSeparator = "(,|\\sand\\s)";\r
-                                       String hierarchiePattern = String.format("%s\\((%s(%s%s)*)\\)",patSingleArea, patSingleArea, patSeparator, patSingleArea);\r
-                                       Pattern patHierarchie = Pattern.compile(hierarchiePattern, Pattern.CASE_INSENSITIVE);\r
-                                       Matcher matcher = patHierarchie.matcher(label); \r
-                                       if (matcher.matches()){\r
-                                               String higherAreaStr = matcher.group(1).trim();\r
-                                               higherArea =  makeArea(state, higherAreaStr, level);\r
-                                               String[] innerAreas = matcher.group(2).split(patSeparator);\r
-                                               for (String innerArea : innerAreas){\r
-                                                       if (isNotBlank(innerArea)){\r
-                                                               NamedArea singleArea = makeArea(state, innerArea.trim(), level);\r
-                                                               areas.add(singleArea);\r
-                                                               NamedArea partOf = singleArea.getPartOf();\r
-//                                                             if (partOf == null){\r
-//                                                                     singleArea.setPartOf(higherArea);\r
-//                                                             }\r
-                                                       }\r
-                                               }\r
-                                       }else{\r
-                                               NamedArea singleArea = makeArea(state, label, level);\r
-                                               areas.add(singleArea);\r
-                                       }\r
-                                       \r
-                                       for (NamedArea area : areas){\r
-                                               //create distribution\r
-                                               Distribution distribution = Distribution.NewInstance(area,status);\r
-                                               description.addElement(distribution);\r
-                                       }\r
-                               } else {\r
-                                       String message = "Empty distribution locality";\r
-                                       fireWarningEvent(message, next, 4);\r
-                               }\r
-                               return text;\r
-                       } else if (isStartingElement(next, COORDINATES)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, COORDINATES)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (next.isCharacters()) {\r
-                               text += next.asCharacters().getData();\r
-                       } else {\r
-                               handleUnexpectedElement(next);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<DistributionLocality> has no closing tag");\r
-       }       \r
-\r
-       private String handleHeading(MarkupImportState state,XMLEventReader reader, XMLEvent parentEvent)throws XMLStreamException {\r
-               checkNoAttributes(parentEvent);\r
-\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               return text;\r
-                       } else if (next.isStartElement()) {\r
-                               if (isStartingElement(next, FOOTNOTE)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else {\r
-                                       handleUnexpectedStartElement(next.asStartElement());\r
-                               }\r
-                       } else if (next.isCharacters()) {\r
-                               text += next.asCharacters().getData();\r
-                       } else {\r
-                               handleUnexpectedEndElement(next.asEndElement());\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<String> has no closing tag");\r
-\r
-       }\r
-\r
-       /**\r
-        * Handle string\r
-        * @param state\r
-        * @param reader\r
-        * @param parentEvent\r
-        * @param feature only needed for distributionLocalities\r
-        * @return\r
-        * @throws XMLStreamException\r
-        */\r
-       private Map<String, String> handleString(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, Feature feature)throws XMLStreamException {\r
-               // attributes\r
-               String classValue = getClassOnlyAttribute(parentEvent, false);\r
-               if (StringUtils.isNotBlank(classValue)) {\r
-                       String message = "class attribute for <string> not yet implemented";\r
-                       fireWarningEvent(message, parentEvent, 2);\r
-               }\r
-\r
-               // subheadings\r
-               Map<String, String> subHeadingMap = new HashMap<String, String>();\r
-               String currentSubheading = null;\r
-\r
-               boolean isTextMode = true;\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               putCurrentSubheading(subHeadingMap, currentSubheading, text);\r
-                               return subHeadingMap;\r
-                       } else if (isStartingElement(next, BR)) {\r
-                               text += "<br/>";\r
-                               isTextMode = false;\r
-                       } else if (isEndingElement(next, BR)) {\r
-                               isTextMode = true;\r
-                       } else if (isHtml(next)) {\r
-                               text += getXmlTag(next);\r
-                       } else if (isStartingElement(next, SUB_HEADING)) {\r
-                               text = putCurrentSubheading(subHeadingMap,currentSubheading, text);\r
-                               // TODO footnotes\r
-                               currentSubheading = getCData(state, reader, next).trim();\r
-                       } else if (isStartingElement(next, DISTRIBUTION_LOCALITY)) {\r
-                               if (feature != null && !feature.equals(Feature.DISTRIBUTION())) {\r
-                                       String message = "Distribution locality only allowed for feature of type 'distribution'";\r
-                                       fireWarningEvent(message, next, 4);\r
-                               }\r
-                               text += handleDistributionLocality(state, reader, next);\r
-                       } else if (next.isCharacters()) {\r
-                               if (! isTextMode) {\r
-                                       String message = "String is not in text mode";\r
-                                       fireWarningEvent(message, next, 6);\r
-                               } else {\r
-                                       text += next.asCharacters().getData();\r
-                               }\r
-                       } else if (isStartingElement(next, HEADING)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isStartingElement(next, VERNACULAR_NAMES)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, HEADING)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, QUOTE)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, QUOTE)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, DEDICATION)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, DEDICATION)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, TAXONTYPE)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, TAXONTYPE)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, FULL_NAME)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, FULL_NAME)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       }else if (isStartingElement(next, REFERENCES)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, REFERENCES)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, GATHERING)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, GATHERING)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, ANNOTATION)) {\r
-                               //TODO  //TODO test handleSimpleAnnotation\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, ANNOTATION)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, HABITAT)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, HABITAT)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, FIGURE_REF)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, FIGURE_REF)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, FIGURE)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, FIGURE)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, FOOTNOTE_REF)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, FOOTNOTE_REF)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, FOOTNOTE)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, FOOTNOTE)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, WRITER)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, WRITER)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else if (isStartingElement(next, DATES)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isEndingElement(next, DATES)) {\r
-                               //TODO\r
-                               popUnimplemented(next.asEndElement());\r
-                       } else {\r
-                               handleUnexpectedElement(next);\r
-                       }\r
-               }\r
-               throw new IllegalStateException("<String> has no closing tag");\r
-       }\r
-\r
-       /**\r
-        * @param subHeadingMap\r
-        * @param currentSubheading\r
-        * @param text\r
-        * @return\r
-        */\r
-       private String putCurrentSubheading(Map<String, String> subHeadingMap, String currentSubheading, String text) {\r
-               if (StringUtils.isNotBlank(text)) {\r
-                       text = removeStartingMinus(text);\r
-                       subHeadingMap.put(currentSubheading, text.trim());\r
-               }\r
-               return "";\r
-       }\r
-\r
-       private String removeStartingMinus(String string) {\r
-               string = replaceStart(string, "-");\r
-               string = replaceStart(string, "\u002d");\r
-               string = replaceStart(string, "\u2013");\r
-               string = replaceStart(string, "\u2014");\r
-               string = replaceStart(string, "--");\r
-               return string;\r
-       }\r
-       \r
-       /**\r
-        * @param value\r
-        * @param replacementString\r
-        */\r
-       private String replaceStart(String value, String replacementString) {\r
-               if (value.startsWith(replacementString) ){\r
-                       value = value.substring(replacementString.length()).trim();\r
-               }\r
-               while (value.startsWith("-") || value.startsWith("\u2014") ){\r
-                       value = value.substring("-".length()).trim();\r
-               }\r
-               return value;\r
-       }\r
-       \r
-       private String getXmlTag(XMLEvent event) {\r
-               String result;\r
-               if (event.isStartElement()) {\r
-                       result = "<" + event.asStartElement().getName().getLocalPart()\r
-                                       + ">";\r
-               } else if (event.isEndElement()) {\r
-                       result = "</" + event.asEndElement().getName().getLocalPart() + ">";\r
-               } else {\r
-                       String message = "Only start or end elements are allowed as Html tags";\r
-                       throw new IllegalStateException(message);\r
-               }\r
-               return result;\r
-       }\r
-\r
-       protected static final List<String> htmlList = Arrays.asList("sub", "sup",\r
-                       "ol", "ul", "li", "i", "b", "table", "br","tr","td");\r
-\r
-       private boolean isHtml(XMLEvent event) {\r
-               if (event.isStartElement()) {\r
-                       String tag = event.asStartElement().getName().getLocalPart();\r
-                       return htmlList.contains(tag);\r
-               } else if (event.isEndElement()) {\r
-                       String tag = event.asEndElement().getName().getLocalPart();\r
-                       return htmlList.contains(tag);\r
-               } else {\r
-                       return false;\r
-               }\r
-\r
-       }\r
-\r
-       /**\r
-        * Handle the char or subchar element. As \r
-        * @param state the import state\r
-        * @param reader \r
-        * @param parentEvent\r
-        * @param parentFeature in case of subchars we need to attache the newly created feature to a parent feature, should be <code>null</code>\r
-        * for top level chars.  \r
-        * @return List of TextData. Not a single one as the recursive TextData will also be returned\r
-        * @throws XMLStreamException\r
-        */\r
-       private List<TextData> handleChar(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, Feature parentFeature) throws XMLStreamException {\r
-               List<TextData> result = new ArrayList<TextData>();\r
-               String classValue = getClassOnlyAttribute(parentEvent);\r
-               Feature feature = makeFeature(classValue, state, parentEvent, parentFeature);\r
-\r
-               boolean isTextMode = true;\r
-               String text = "";\r
-               while (reader.hasNext()) {\r
-                       XMLEvent next = readNoWhitespace(reader);\r
-                       if (isMyEndingElement(next, parentEvent)) {\r
-                               state.putFeatureToCharSorterList(feature);\r
-                               TextData textData = TextData.NewInstance(feature);\r
-                               textData.putText(getDefaultLanguage(state), text);\r
-                               result.add(textData);\r
-                               return result;\r
-                       } else if (isStartingElement(next, FIGURE_REF)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isStartingElement(next, FOOTNOTE_REF)) {\r
-                               //TODO\r
-                               handleNotYetImplementedElement(next);\r
-                       } else if (isStartingElement(next, BR)) {\r
-                               text += "<br/>";\r
-                               isTextMode = false;\r
-                       } else if (isEndingElement(next, BR)) {\r
-                               isTextMode = true;\r
-                       } else if (isHtml(next)) {\r
-                               text += getXmlTag(next);\r
-                       } else if (next.isStartElement()) {\r
-                               if (isStartingElement(next, ANNOTATION)) {\r
-                                       handleNotYetImplementedElement(next); //TODO test handleSimpleAnnotation\r
-                               } else if (isStartingElement(next, ITALICS)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, BOLD)) {\r
-                                       handleNotYetImplementedElement(next);\r
-                               } else if (isStartingElement(next, FIGURE)) {\r
-                                       handleFigure(state, reader, next);\r
-                               } else if (isStartingElement(next, SUB_CHAR)) {\r
-                                       List<TextData> textData = handleChar(state, reader, next, feature);\r
-                                       result.addAll(textData);\r
-                               } else if (isStartingElement(next, FOOTNOTE)) {\r
-                                       FootnoteDataHolder footnote = handleFootnote(state, reader,     next);\r
-                                       if (footnote.isRef()) {\r
-                                               String message = "Ref footnote not implemented here";\r
-                                               fireWarningEvent(message, next, 4);\r
-                                       } else {\r
-                                               registerGivenFootnote(state, footnote);\r
-                                       }\r
-                               } else {\r
-                                       handleUnexpectedStartElement(next.asStartElement());\r
-                               }\r
-                       } else if (next.isCharacters()) {\r
-                               if (!isTextMode) {\r
-                                       String message = "String is not in text mode";\r
-                                       fireWarningEvent(message, next, 6);\r
-                               } else {\r
-                                       text += next.asCharacters().getData();\r
-                               }\r
-                       } else {\r
-                               handleUnexpectedEndElement(next.asEndElement());\r
-                       }\r
-               }\r
-               throw new IllegalStateException("RefPart has no closing tag");\r
-       }\r
-\r
-       /**\r
-        * @param classValue\r
-        * @param state\r
-        * @param parentEvent\r
-        * @param parentFeature \r
-        * @return\r
-        * @throws UndefinedTransformerMethodException\r
-        */\r
-       private Feature makeFeature(String classValue, MarkupImportState state, XMLEvent parentEvent, Feature parentFeature) {\r
-               UUID uuid;\r
-               try {\r
-                       String featureText = StringUtils.capitalize(classValue);\r
-                       if (parentFeature != null){\r
-                               featureText = "<%s>" + featureText;\r
-                               featureText = String.format(featureText, parentFeature.getTitleCache());\r
-                               classValue = "<%s>" + classValue;\r
-                               classValue = String.format(classValue, parentFeature.getTitleCache());\r
-                       }\r
-\r
-                       \r
-                       Feature feature = state.getTransformer().getFeatureByKey(classValue);\r
-                       if (feature != null) {\r
-                               return feature;\r
-                       }\r
-                       uuid = state.getTransformer().getFeatureUuid(classValue);\r
-                       if (uuid == null) {\r
-                               uuid = state.getFeatureUuid(classValue);\r
-                       }                       \r
-                       if (uuid == null) {\r
-                               // TODO\r
-                               String message = "Uuid is not defined for '%s'";\r
-                               message = String.format(message, classValue);\r
-                               fireWarningEvent(message, parentEvent, 8);\r
-                               uuid = UUID.randomUUID();\r
-                               state.putFeatureUuid(classValue, uuid);\r
-                       }\r
-\r
-                       // TODO eFlora vocabulary\r
-                       TermVocabulary<Feature> voc = null;\r
-                       feature = getFeature(state, uuid, featureText, featureText, classValue, voc);\r
-                       if (parentFeature != null){\r
-                               parentFeature.addIncludes(feature);\r
-                               save(parentFeature, state);\r
-                       }\r
-                       save(feature, state);\r
-                                       \r
-                       if (feature == null) {\r
-                               throw new NullPointerException(classValue + " not recognized as a feature");\r
-                       }\r
-//                     state.putFeatureToCurrentList(feature);\r
-                       return feature;\r
-               } catch (Exception e) {\r
-                       String message = "Could not create feature for %s: %s";\r
-                       message = String.format(message, classValue, e.getMessage());\r
-                       fireWarningEvent(message, parentEvent, 4);\r
-                       e.printStackTrace();\r
-                       return Feature.UNKNOWN();\r
-               }\r
-       }\r
-\r
-\r
 \r
 }\r