import eu.etaxonomy.cdm.model.name.Rank;\r
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;\r
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;\r
+import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImplRegExBase;\r
\r
\r
/**\r
\r
protected String getGenusOrUninomialNameCache(NonViralName nonViralName){\r
String result;\r
- result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();\r
+ result = getUninomialPart(nonViralName);\r
result = addAppendedPhrase(result, nonViralName).trim();\r
return result;\r
}\r
+\r
+\r
+ private String getUninomialPart(NonViralName nonViralName) {\r
+ String result;\r
+ result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();\r
+ if (nonViralName.isMonomHybrid()){\r
+ result = NonViralNameParserImplRegExBase.hybridSign + result; \r
+ }\r
+ return result;\r
+ }\r
\r
protected String getInfraGenusNameCache(NonViralName nonViralName){\r
String result;\r
infraGenericMarker = "'unhandled infrageneric rank'";\r
}\r
}\r
- result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();\r
+ result = getUninomialPart(nonViralName);\r
result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");\r
result = addAppendedPhrase(result, nonViralName).trim();\r
return result;\r
if (includeMarker){ \r
result += " " + (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");\r
}\r
- result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim().replace("null", "");\r
+ String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());\r
+ if (nonViralName.isTrinomHybrid()){\r
+ infrSpecEpi = NonViralNameParserImplRegExBase.hybridSign + infrSpecEpi; \r
+ }\r
+ result += " " + (infrSpecEpi).trim().replace("null", "");\r
result = addAppendedPhrase(result, nonViralName).trim();\r
return result;\r
}\r
\r
private String getGenusAndSpeciesPart(NonViralName nonViralName) {\r
String result;\r
- result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();\r
- if (StringUtils.isNotBlank(nonViralName.getInfraGenericEpithet()) ){\r
- result += " (" + nonViralName.getInfraGenericEpithet().trim() + ")";\r
+ //Uninomial\r
+ result = getUninomialPart(nonViralName);\r
+ \r
+ //InfraGenericEpi\r
+ boolean hasInfraGenericEpi = StringUtils.isNotBlank(nonViralName.getInfraGenericEpithet());\r
+ if (hasInfraGenericEpi){\r
+ String infrGenEpi = nonViralName.getInfraGenericEpithet().trim();\r
+ if (nonViralName.isBinomHybrid()){\r
+ infrGenEpi = NonViralNameParserImplRegExBase.hybridSign + infrGenEpi; \r
+ }\r
+ result += " (" + infrGenEpi + ")";\r
+ }\r
+ //Species Epi\r
+ String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim();\r
+ if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() || \r
+ hasInfraGenericEpi && nonViralName.isTrinomHybrid()){\r
+ specEpi = NonViralNameParserImplRegExBase.hybridSign + specEpi; \r
}\r
- result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim()).replace("null", "");\r
+ result += " " + (specEpi).replace("null", "");\r
return result;\r
}\r
\r
// OLD: fullName = oWsRE.subst(fullName, " "); //substitute multiple whitespaces \r
fullNameString = fullNameString.trim();\r
\r
+ fullNameString = removeHybridBlanks(fullNameString);\r
String[] epi = pattern.split(fullNameString);\r
try {\r
//cultivars //TODO 2 implement cultivars\r
// }\r
//hybrids //TODO 2 implement hybrids\r
//else \r
- if (hybridPattern.matcher(fullNameString).matches() ){\r
- nameToBeFilled = parseHybrid(fullNameString);\r
- }\r
- else if (genusOrSupraGenusPattern.matcher(fullNameString).matches()){\r
+// if (hybridPattern.matcher(fullNameString).find() ){\r
+// parseHybrid(nameToBeFilled, fullNameString, rank, makeEmpty);\r
+// } else \r
+ if (genusOrSupraGenusPattern.matcher(fullNameString).matches()){\r
//supraGeneric\r
if (rank != null && ! hasCheckRankProblem && (rank.isSupraGeneric()|| rank.isGenus())){\r
nameToBeFilled.setRank(rank);\r
nameToBeFilled.setGenusOrUninomial(epi[0]);\r
} \r
- //genus or guess rank\r
- else {\r
+ //genus or guess rank\r
+ else {\r
rank = guessUninomialRank(nameToBeFilled, epi[0]); \r
nameToBeFilled.setRank(rank);\r
nameToBeFilled.setGenusOrUninomial(epi[0]);\r
}\r
authorString = fullNameString.substring(epi[0].length());\r
}\r
- //infra genus\r
- else if (infraGenusPattern.matcher(fullNameString).matches()){\r
+ //infra genus\r
+ else if (infraGenusPattern.matcher(fullNameString).matches()){\r
nameToBeFilled.setRank(Rank.getRankByAbbreviation(epi[1]));\r
nameToBeFilled.setGenusOrUninomial(epi[0]);\r
nameToBeFilled.setInfraGenericEpithet(epi[2]);\r
authorString = fullNameString.substring(epi[0].length() + 1 + epi[1].length()+ 1 + epi[2].length());\r
}\r
- //aggr. or group\r
- else if (aggrOrGroupPattern.matcher(fullNameString).matches()){\r
+ //aggr. or group\r
+ else if (aggrOrGroupPattern.matcher(fullNameString).matches()){\r
nameToBeFilled.setRank(Rank.getRankByAbbreviation(epi[2]));\r
nameToBeFilled.setGenusOrUninomial(epi[0]);\r
nameToBeFilled.setSpecificEpithet(epi[1]);\r
}\r
- //species\r
- else if (speciesPattern.matcher(fullNameString).matches()){\r
+ //species\r
+ else if (speciesPattern.matcher(fullNameString).matches()){\r
nameToBeFilled.setRank(Rank.SPECIES());\r
nameToBeFilled.setGenusOrUninomial(epi[0]);\r
nameToBeFilled.setSpecificEpithet(epi[1]);\r
authorString = fullNameString.substring(epi[0].length() + 1 + epi[1].length());\r
}\r
- //autonym\r
- else if (autonymPattern.matcher(fullNameString).matches()){\r
+ //autonym\r
+ else if (autonymPattern.matcher(fullNameString).matches()){\r
nameToBeFilled.setRank(Rank.getRankByAbbreviation(epi[epi.length - 2]));\r
nameToBeFilled.setGenusOrUninomial(epi[0]);\r
nameToBeFilled.setSpecificEpithet(epi[1]);\r
int lenInfraSpecies = 2 + epi[epi.length - 2].length() + epi[epi.length - 1].length();\r
authorString = fullNameString.substring(lenSpecies, fullNameString.length() - lenInfraSpecies);\r
}\r
- //infraSpecies\r
- else if (infraSpeciesPattern.matcher(fullNameString).matches()){\r
+ //infraSpecies\r
+ else if (infraSpeciesPattern.matcher(fullNameString).matches()){\r
String infraSpecRankEpi = epi[2];\r
String infraSpecEpi = epi[3];\r
if ("tax.".equals(infraSpecRankEpi)){\r
nameToBeFilled.setInfraSpecificEpithet(infraSpecEpi);\r
authorString = fullNameString.substring(epi[0].length()+ 1 + epi[1].length() +1 + infraSpecRankEpi.length() + 1 + infraSpecEpi.length());\r
}//old infraSpecies\r
- else if (oldInfraSpeciesPattern.matcher(fullNameString).matches()){\r
+ else if (oldInfraSpeciesPattern.matcher(fullNameString).matches()){\r
boolean implemented = false;\r
if (implemented){\r
nameToBeFilled.setRank(Rank.getRankByNameOrAbbreviation(epi[2]));\r
// END\r
logger.info("no applicable parsing rule could be found for \"" + fullNameString + "\"");\r
}\r
+ //hybrid bits \r
+ handleHybridBits(nameToBeFilled);\r
//authors\r
if (nameToBeFilled != null && StringUtils.isNotBlank(authorString) ){ \r
handleAuthors(nameToBeFilled, fullNameString, authorString);\r
}\r
}\r
\r
+ private void handleHybridBits(NonViralName nameToBeFilled) {\r
+ //uninomial\r
+ String uninomial = CdmUtils.Nz(nameToBeFilled.getGenusOrUninomial());\r
+ boolean isUninomialHybrid = uninomial.startsWith(hybridSign);\r
+ if (isUninomialHybrid){\r
+ nameToBeFilled.setMonomHybrid(true);\r
+ nameToBeFilled.setGenusOrUninomial(uninomial.replace(hybridSign, ""));\r
+ }\r
+ //infrageneric\r
+ String infrageneric = CdmUtils.Nz(nameToBeFilled.getInfraGenericEpithet());\r
+ boolean isInfraGenericHybrid = infrageneric.startsWith(hybridSign);\r
+ if (isInfraGenericHybrid){\r
+ nameToBeFilled.setBinomHybrid(true);\r
+ nameToBeFilled.setInfraGenericEpithet(infrageneric.replace(hybridSign, ""));\r
+ }\r
+ //species Epi\r
+ String speciesEpi = CdmUtils.Nz(nameToBeFilled.getSpecificEpithet());\r
+ boolean isSpeciesHybrid = speciesEpi.startsWith(hybridSign);\r
+ if (isSpeciesHybrid){\r
+ if (StringUtils.isBlank(infrageneric)){\r
+ nameToBeFilled.setBinomHybrid(true);\r
+ }else{\r
+ nameToBeFilled.setTrinomHybrid(true);\r
+ }\r
+ nameToBeFilled.setSpecificEpithet(speciesEpi.replace(hybridSign, ""));\r
+ }\r
+ //infra species\r
+ String infraSpeciesEpi = CdmUtils.Nz(nameToBeFilled.getInfraSpecificEpithet());\r
+ boolean isInfraSpeciesHybrid = infraSpeciesEpi.startsWith(hybridSign);\r
+ if (isInfraSpeciesHybrid){\r
+ nameToBeFilled.setTrinomHybrid(true);\r
+ nameToBeFilled.setInfraSpecificEpithet(infraSpeciesEpi.replace(hybridSign, ""));\r
+ }\r
+ \r
+ }\r
+\r
+ private String removeHybridBlanks(String fullNameString) {\r
+ fullNameString = fullNameString.replaceAll(hybridFull, " "+hybridSign).trim();\r
+ return fullNameString;\r
+ }\r
+\r
/**\r
* Author parser for external use\r
* @param nonViralName\r
}\r
}else {\r
//TODO\r
- logger.warn ("not yet implemented");\r
+ logger.warn ("Full author String parsable only for defined BotanicalNames or ZoologicalNames but this is " + clazz.getSimpleName());\r
throw new StringNotParsableException("fullAuthorString (" +fullAuthorString+") not parsable: ");\r
}\r
fullAuthorsChecked(fullAuthorString, authors, years);\r
\r
\r
//Parsing of the given full name that has been identified as hybrid already somewhere else.\r
- private BotanicalName parseHybrid(String fullName){\r
+ private void parseHybrid(NonViralName nameToBeFilled, String fullNameString, Rank rank, boolean makeEmpty){\r
logger.warn("parseHybrid --> function not yet implemented");\r
- BotanicalName result = BotanicalName.NewInstance(null);\r
- result.setTitleCache(fullName,true);\r
- return result;\r
+ \r
+// String nonHybridName = fullNameString;\r
+// boolean isMonomHybrid = isMonomHybrid(fullNameString);\r
+// if (isMonomHybrid){\r
+// nonHybridName.replaceAll(hybrid, "");\r
+// }\r
+// \r
+// String[] split = nonHybridName.split("\\s");\r
+// parseFullName(nameToBeFilled, nonHybridName, rank, makeEmpty);\r
+// \r
+// nonHybridName = nonHybridName.replaceAll(hybrid, " ");\r
+//\r
+// boolean isBinomHybrid = isBinomHybrid(split);\r
+//// boolean isTrinomHybrid = isTrinomHybrid(split);\r
+// \r
+// nonHybridName = nonHybridName.replaceAll(hybrid, " ");\r
+// \r
+// parseFullName(nameToBeFilled, nonHybridName, rank, makeEmpty);\r
+// nameToBeFilled.getTitleCache();\r
+// nameToBeFilled.setMonomHybrid(isMonomHybrid);\r
+// nameToBeFilled.setBinomHybrid(isBinomHybrid);\r
+// nameToBeFilled.setBinomHybrid(isTrinomHybrid);\r
+ \r
+ nameToBeFilled.setTitleCache(fullNameString,true);\r
+ return;\r
}\r
\r
+// private boolean isBinomHybrid(String[] split) {\r
+// if (){\r
+// \r
+// }\r
+// return false;\r
+// }\r
+\r
+ private boolean isMonomHybrid(String fullNameString) {\r
+ Matcher matcher = hybridPattern.matcher(fullNameString);\r
+ boolean find = matcher.find();\r
+ int start = matcher.start();\r
+ if (find == true && start == 0){\r
+ return true;\r
+ }else{\r
+ return false;\r
+ }\r
+ }\r
+\r
// // Parsing of the given full name that has been identified as a cultivar already somwhere else.\r
// // The ... cv. ... syntax is not covered here as it is not according the rules for naming cultivars.\r
public BotanicalName parseCultivar(String fullName) throws StringNotParsableException{\r
public abstract class NonViralNameParserImplRegExBase {\r
@SuppressWarnings("unused")\r
private static final Logger logger = Logger.getLogger(NonViralNameParserImplRegExBase.class);\r
- \r
+\r
// good intro: http://java.sun.com/docs/books/tutorial/essential/regex/index.html\r
\r
//splitter\r
protected static String epiSplitter = "(\\s+|\\(|\\))"; //( ' '+| '(' | ')' )\r
protected static Pattern pattern = Pattern.compile(epiSplitter); \r
- \r
+\r
+ public static final String hybridSign = "\u00D7";\r
+\r
//some useful non-terminals\r
protected static String pStart = "^";\r
protected static String end = "$";\r
//cultivars and hybrids\r
protected static String cultivar = oWs + "'..+'"; //Achtung mit Hochkomma in AuthorNamen\r
protected static String cultivarMarker = oWs + "(cv.|')";\r
- protected static String hybrid = oWs + "((x|X)" + oWs + "|notho)";//= ( x )|( X )|( notho)\r
+ protected static String hybridPart = "((x|X)" + oWs + "|"+hybridSign+"|notho)";\r
+ protected static String hybridFull = "(" +oWs +"|"+ pStart +")" + hybridPart;\r
+ \r
\r
// Name String\r
- protected static String genusOrSupraGenus = capitalEpiWord;\r
+ protected static String genusOrSupraGenus = "("+hybridFull+")?" + capitalEpiWord;\r
protected static String infraGenus = capitalEpiWord + oWs + InfraGenusMarker + oWs + capitalEpiWord;\r
protected static String aggrOrGroup = capitalEpiWord + oWs + nonCapitalEpiWord + oWs + aggrOrGroupMarker;\r
- protected static String species = capitalEpiWord + oWs + nonCapitalEpiWord;\r
- protected static String infraSpecies = capitalEpiWord + oWs + nonCapitalEpiWord + oWs + infraSpeciesMarker + oWs + nonCapitalEpiWord;\r
+ protected static String species = genusOrSupraGenus + oWs + "("+hybridPart+")?" + nonCapitalEpiWord;\r
+ protected static String infraSpecies = species + oWs + infraSpeciesMarker + oWs + "("+hybridPart+")?" + nonCapitalEpiWord;\r
protected static String oldInfraSpecies = capitalEpiWord + oWs + nonCapitalEpiWord + oWs + oldInfraSpeciesMarker + oWs + nonCapitalEpiWord;\r
protected static String autonym = capitalEpiWord + oWs + "(" + nonCapitalEpiWord +")" + oWs + fullBotanicAuthorString + oWs + infraSpeciesMarker + oWs + "\\1"; //2-nd word and last word are the same \r
//autonym pattern used within anyBotanicalFullName pattern\r
protected static Pattern teamSplitterPattern = Pattern.compile(teamSplitter);\r
protected static Pattern cultivarPattern = Pattern.compile(cultivar);\r
protected static Pattern cultivarMarkerPattern = Pattern.compile(cultivarMarker);\r
- protected static Pattern hybridPattern = Pattern.compile(hybrid); \r
+ protected static Pattern hybridPattern = Pattern.compile(hybridFull); \r
\r
protected static Pattern genusOrSupraGenusPattern = Pattern.compile(pStart + genusOrSupraGenus + facultFullAuthorString2 + end);\r
protected static Pattern infraGenusPattern = Pattern.compile(pStart + infraGenus + facultFullAuthorString2 + end);\r
\r
import java.util.List;\r
\r
-import junit.framework.Assert;\r
+import org.junit.Assert;\r
\r
import org.apache.log4j.Logger;\r
import org.junit.Before;\r
assertEquals(atomizedTitleCache, speciesName.getFullTitleCache()); \r
}\r
\r
+ /**\r
+ * Test method for {@link eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy#getAuthorshipCache(eu.etaxonomy.cdm.model.name.NonViralName)}.\r
+ */\r
+ @Test\r
+ public void testHybridNames() {\r
+ this.speciesName.setCombinationAuthorTeam(author);\r
+ Assert.assertEquals(author.getNomenclaturalTitle(), speciesName.getAuthorshipCache());\r
+ Assert.assertEquals("Should be Abies alba L.", "Abies alba L.", speciesName.getTitleCache());\r
+ \r
+ speciesName.setBinomHybrid(true);\r
+ //TODO\r
+// speciesName.setTitleCache(null, false);\r
+// speciesName.setNameCache(null, false);\r
+ Assert.assertEquals("Should be Abies ×alba L.", "Abies ×alba L.", speciesName.getTitleCache());\r
+ speciesName.setMonomHybrid(true);\r
+ speciesName.setTitleCache(null, false);\r
+ speciesName.setNameCache(null, false);\r
+ Assert.assertEquals("Should be '×Abies ×alba L.'", "×Abies ×alba L.", speciesName.getTitleCache());\r
+ \r
+ Assert.assertEquals("Should be 'Genus'", "Genus", genusName.getTitleCache());\r
+ genusName.setMonomHybrid(true);\r
+ genusName.setTitleCache(null, false);\r
+ genusName.setNameCache(null, false);\r
+ Assert.assertEquals("Should be '×Genus'", "×Genus", genusName.getTitleCache());\r
+ \r
+ Assert.assertEquals("Should be 'Abies alba subsp. beta'", subSpeciesNameString, subSpeciesName.getTitleCache());\r
+ subSpeciesName.setTrinomHybrid(true);\r
+ subSpeciesName.setTitleCache(null, false);\r
+ subSpeciesName.setNameCache(null, false);\r
+ Assert.assertEquals("Should be 'Abies alba subsp. ×beta'", "Abies alba subsp. ×beta", subSpeciesName.getTitleCache());\r
+ subSpeciesName.setMonomHybrid(true);\r
+ subSpeciesName.setTitleCache(null, false);\r
+ subSpeciesName.setNameCache(null, false);\r
+ Assert.assertEquals("Should be '×Abies alba subsp. ×beta'", "×Abies alba subsp. ×beta", subSpeciesName.getTitleCache());\r
+ }\r
+ \r
@Test\r
public void testCacheListener() {\r
Reference ref = ReferenceFactory.newGeneric();\r
termInitializer.initialize();\r
}\r
\r
- /**\r
- * @throws java.lang.Exception\r
- */\r
- @AfterClass\r
- public static void tearDownAfterClass() throws Exception {\r
- }\r
\r
/**\r
* @throws java.lang.Exception\r
botanicCode = NomenclaturalCode.ICBN;\r
}\r
\r
- /**\r
- * @throws java.lang.Exception\r
- */\r
- @After\r
- public void tearDown() throws Exception {\r
- }\r
\r
/*************** TEST *********************************************/\r
\r
assertEquals("Basionym author should have 3 authors", 3, ((Team)authorname.getExBasionymAuthorTeam()).getTeamMembers().size());\r
}\r
\r
+ /**\r
+ * Test method for {@link eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl#parseFullName(java.lang.String, eu.etaxonomy.cdm.model.name.Rank)}.\r
+ */\r
+ @Test\r
+ public final void testHybrids() {\r
+ try {\r
+ Method parseMethod = parser.getClass().getDeclaredMethod("parseFullName", String.class, NomenclaturalCode.class, Rank.class);\r
+ testName_StringNomcodeRank(parseMethod);\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ assertTrue(false);\r
+ }\r
+ \r
+ //Species hybrid\r
+// NonViralName nameTeam1 = parser.parseFullName("Aegilops ×insulae-cypri H. Scholz");\r
+ NonViralName name1 = parser.parseFullName("Aegilops ×insulae Scholz", botanicCode, null);\r
+ assertTrue("Name must have binom hybrid bit set", name1.isBinomHybrid());\r
+ assertFalse("Name must not have monom hybrid bit set", name1.isMonomHybrid());\r
+ assertFalse("Name must not have trinom hybrid bit set", name1.isTrinomHybrid());\r
+ assertEquals("Species epithet must be 'insulae'", "insulae", name1.getSpecificEpithet());\r
+ \r
+ //Uninomial hybrid\r
+ name1 = parser.parseFullName("x Aegilops Scholz", botanicCode, null);\r
+ assertTrue("Name must have monom hybrid bit set", name1.isMonomHybrid());\r
+ assertFalse("Name must not have binom hybrid bit set", name1.isBinomHybrid());\r
+ assertFalse("Name must not have trinom hybrid bit set", name1.isTrinomHybrid());\r
+ assertEquals("Uninomial must be 'Aegilops'", "Aegilops", name1.getGenusOrUninomial());\r
+\r
+ //Species hybrid\r
+ name1 = parser.parseFullName("Aegilops insulae subsp. X abies Scholz", botanicCode, null);\r
+ assertFalse("Name must not have monom hybrid bit set", name1.isMonomHybrid());\r
+ assertFalse("Name must not have binom hybrid bit set", name1.isBinomHybrid());\r
+ assertTrue("Name must have trinom hybrid bit set", name1.isTrinomHybrid());\r
+ assertEquals("Infraspecific epithet must be 'abies'", "abies", name1.getInfraSpecificEpithet());\r
+\r
+ }\r
+ \r
private void testName_StringNomcodeRank(Method parseMethod) \r
throws InvocationTargetException, IllegalAccessException {\r
NonViralName name1 = (NonViralName)parseMethod.invoke(parser, strNameAbies1, null, Rank.SPECIES());\r
\r
}\r
\r
+ \r
+ \r
/**\r
* @param testParsable\r
* @param icbn\r