import java.util.Map;\r
import java.util.Set;\r
\r
+import javax.xml.stream.Location;\r
import javax.xml.stream.XMLEventReader;\r
import javax.xml.stream.XMLStreamException;\r
import javax.xml.stream.events.Attribute;\r
import eu.etaxonomy.cdm.model.description.KeyStatement;\r
import eu.etaxonomy.cdm.model.description.PolytomousKey;\r
import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
+import eu.etaxonomy.cdm.model.name.BotanicalName;\r
import eu.etaxonomy.cdm.model.name.NonViralName;\r
import eu.etaxonomy.cdm.model.name.Rank;\r
import eu.etaxonomy.cdm.model.taxon.Taxon;\r
\r
private static final String COUPLET = "couplet";\r
private static final String IS_SPOTCHARACTERS = "isSpotcharacters";\r
+ private static final String ONLY_NUMBERED_TAXA_EXIST = "onlyNumberedTaxaExist";\r
+ private static final String EXISTS = "exists";\r
private static final String KEYNOTES = "keynotes";\r
private static final String KEY_TITLE = "keyTitle";\r
private static final String QUESTION = "question";\r
String message = "Attribute isSpotcharacters not yet implemented for <key>";\r
fireWarningEvent(message, parentEvent, 4);\r
}\r
+ boolean onlyNumberedTaxaExist = checkAndRemoveAttributeValue(attributes, ONLY_NUMBERED_TAXA_EXIST, "true");\r
+ state.setOnlyNumberedTaxaExist(onlyNumberedTaxaExist);\r
\r
PolytomousKey key = PolytomousKey.NewInstance();\r
key.addTaxonomicScope(state.getCurrentTaxon());\r
XMLEvent next = readNoWhitespace(reader);\r
if (isMyEndingElement(next, parentEvent)) {\r
save(key, state);\r
+ //reset state\r
state.setCurrentKey(null);\r
+ state.setOnlyNumberedTaxaExist(false);\r
return;\r
} else if (isEndingElement(next, KEYNOTES)){\r
popUnimplemented(next.asEndElement());\r
if (parentNode != null){\r
for (PolytomousKeyNode childNode : childList){\r
parentNode.addChild(childNode);\r
+ //just to be on the save side\r
+ parentNode.refreshNodeNumbering();\r
}\r
}else if (isNotBlank(num)){\r
UnmatchedLeadsKey unmatchedKey = UnmatchedLeadsKey.NewInstance(state.getCurrentKey(), num);\r
for(PolytomousKeyNode nodeToMatch: nodes){\r
for (PolytomousKeyNode childNode : childList){\r
nodeToMatch.addChild(childNode);\r
+ //just to be on the save side\r
+ nodeToMatch.refreshNodeNumbering();\r
}\r
state.getUnmatchedLeads().removeNode(unmatchedKey, nodeToMatch);\r
}\r
private void handleQuestion(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, List<PolytomousKeyNode> nodesList) throws XMLStreamException {\r
// attributes\r
Map<String, Attribute> attributes = getAttributes(parentEvent);\r
- //needed only for data lineage\r
+ //TODO needed only for data lineage\r
String questionNum = getAndRemoveRequiredAttributeValue(parentEvent, attributes, NUM);\r
\r
PolytomousKeyNode myNode = PolytomousKeyNode.NewInstance();\r
String num = getOnlyAttribute(next, NUM, true);\r
String cData = getCData(state, reader, next, false);\r
if (isNotBlank(cData) && ! cData.equals(num)){\r
- String message = "CData ('%s') not handled in <toCouplet>";\r
+ String message = "CData ('%s') not be handled in <toCouplet>";\r
message = String.format(message, cData);\r
fireWarningEvent(message, next, 4);\r
}\r
private void handleToTaxon(MarkupImportState state, XMLEventReader reader, XMLEvent parentEvent, PolytomousKeyNode node) throws XMLStreamException {\r
Map<String, Attribute> attributes = getAttributes(parentEvent);\r
String num = getAndRemoveAttributeValue(attributes, NUM);\r
- String taxonStr = getCData(state, reader, parentEvent, false).trim();\r
- if (taxonStr.endsWith(".")){\r
- taxonStr = taxonStr.substring(0, taxonStr.length()-1).trim();\r
- }\r
+ boolean taxonNotExists = checkAndRemoveAttributeValue(attributes, EXISTS, "false");\r
+ \r
+ String taxonCData = getCData(state, reader, parentEvent, false).trim();\r
+ \r
//TODO ?\r
- taxonStr = makeTaxonKey(taxonStr, state.getCurrentTaxon());\r
- UnmatchedLeadsKey unmatched = UnmatchedLeadsKey.NewInstance(num, taxonStr);\r
- state.getUnmatchedLeads().addKey(unmatched, node);\r
+ String taxonKeyStr = makeTaxonKey(taxonCData, state.getCurrentTaxon(), parentEvent.getLocation());\r
+ taxonNotExists = taxonNotExists || (isBlank(num) && state.isOnlyNumberedTaxaExist());\r
+ if (taxonNotExists){\r
+ Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.UNKNOWN_RANK()), null);\r
+ taxon.getName().setTitleCache(taxonKeyStr, true);\r
+ node.setTaxon(taxon);\r
+ }else{\r
+ UnmatchedLeadsKey unmatched = UnmatchedLeadsKey.NewInstance(num, taxonKeyStr);\r
+ state.getUnmatchedLeads().addKey(unmatched, node);\r
+ }\r
return;\r
}\r
\r
\r
- private String makeTaxonKey(String strGoto, Taxon taxon) {\r
+ /**\r
+ * Creates a string that represents the given taxon. The string will try to replace e.g.\r
+ * abbreviated genus epithets by its full name etc.\r
+ * @param strGoto\r
+ * @param taxon\r
+ * @param location \r
+ * @return\r
+ */\r
+ private String makeTaxonKey(String strGoto, Taxon taxon, Location location) {\r
String result = "";\r
if (strGoto == null){\r
return "";\r
NonViralName<?> name = CdmBase.deproxy(taxon.getName(), NonViralName.class);\r
String strGenusName = name.getGenusOrUninomial();\r
\r
- \r
- strGoto = strGoto.replaceAll("\\([^\\(\\)]*\\)", ""); //replace all brackets\r
+ String bracketPattern = ".*\\([^\\(\\)]*\\).*";\r
+ if (strGoto.matches(bracketPattern)){\r
+ fireWarningEvent("toTaxon has bracket", makeLocationStr(location), 4);\r
+ strGoto = strGoto.replaceAll(bracketPattern, ""); //replace all brackets\r
+ }\r
strGoto = strGoto.replaceAll("\\s+", " "); //replace multiple whitespaces by exactly one whitespace\r
\r
strGoto = strGoto.trim(); \r
String[] split = strGoto.split("\\s");\r
+ //handle single epithets and markers\r
for (int i = 0; i<split.length; i++){\r
String single = split[i];\r
if (isGenusAbbrev(single, strGenusName)){\r
}\r
result = (result + " " + split[i]).trim();\r
}\r
+ //remove trailing "."\r
+ if (result.endsWith(".")){\r
+ result = result.substring(0, result.length()-1).trim();\r
+ }\r
return result;\r
}\r
\r
for (PolytomousKeyNode matchingNode : matchingNodes){\r
state.getUnmatchedLeads().removeNode(leadsKey, matchingNode);\r
matchingNode.setTaxon(taxon);\r
+ //just to be on the save side\r
+ matchingNode.refreshNodeNumbering();\r
state.getPolytomousKeyNodesToSave().add(matchingNode);\r
}\r
return matchingNodes;\r