@Test public void cas24() throws ParsingException{ String name = CASTools.uninvertCASName("Pyrrolo[1,2-a]pyrimidinium, 1-[4-[(aminoiminomethyl)amino]butyl]-7-[[2-[(aminoiminomethyl)-amino]ethyl]thio]-6-(11-dodecenyl)-2,3,4,6,7,8-hexahydro-6-hydroxy-, chloride, dihydrochloride", parseRules); assertEquals("1-[4-[(aminoiminomethyl)amino]butyl]-7-[[2-[(aminoiminomethyl)-amino]ethyl]thio]-6-(11-dodecenyl)-2,3,4,6,7,8-hexahydro-6-hydroxy-Pyrrolo[1,2-a]pyrimidinium chloride dihydrochloride", name); }
static String uninvertCASName(String name, ParseRules parseRules) throws ParsingException { List<String> nameComponents = new ArrayList<String>(Arrays.asList(matchCommaSpace.split(name))); List<String> substituents = new ArrayList<String>(); List<String> seperateWordSubstituents = new ArrayList<String>(); List<String> functionalTerms = new ArrayList<String>(); String parent = nameComponents.get(0); String[] parentNameParts = parent.split(" "); if (parentNameParts.length != 1) { if (matchCasCollectiveIndex.matcher(parentNameParts[parentNameParts.length - 1]).matches()) { StringBuilder parentSB = new StringBuilder(); for (int i = 0; i < parentNameParts.length - 1; i++) { parentSB.append(parentNameParts[i]); } parent = parentSB.toString(); parentNameParts = parent.split(" "); } for (int i = 1; i < parentNameParts.length; i++) { if (!matchAcid.matcher(parentNameParts[i]).matches()) { ParseRulesResults results = parseRules.getParses(parentNameParts[i]); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.isEmpty()) { throw new ParsingException("Invalid CAS name. Parent compound was followed by an unexpected term"); } } } } boolean addedBracket = false; boolean esterEncountered = false; for (int i = 1; i < nameComponents.size(); i++) { String nameComponent = nameComponents.get(i); Matcher m = matchCompoundWithPhrase.matcher(nameComponent); boolean compoundWithcomponent = false; if (m.lookingAt()) { nameComponent = nameComponent.substring(m.group().length()); compoundWithcomponent = true; } String[] components = nameComponents.get(i).split(" "); for (int c = 0, componentLen = components.length; c < componentLen; c++) { String component = components[c]; if (compoundWithcomponent) { functionalTerms.add(component); continue; } if (component.endsWith("-")) { Character missingCloseBracket = missingCloseBracketCharIfApplicable(component); if (missingCloseBracket !=null) { if (addedBracket) { throw new ParsingException("Close bracket appears to be missing"); } parent += missingCloseBracket; addedBracket = true; } substituents.add(component); } else { ParseRulesResults results = parseRules.getParses(component); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.size() > 0) { List<ParseWord> parseWords = WordTools.splitIntoParseWords(parseTokens, component); List<ParseTokens> firstParseWordTokens = parseWords.get(0).getParseTokens(); WordType firstWordType = OpsinTools.determineWordType(firstParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < firstParseWordTokens.size(); j++) { if (!firstWordType.equals(OpsinTools.determineWordType(firstParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (parseWords.size() == 1) { switch (firstWordType) { case functionalTerm: if (component.equalsIgnoreCase("ester")) { if (seperateWordSubstituents.size() ==0){ throw new ParsingException("ester encountered but no substituents were specified in potential CAS name!"); } if (esterEncountered) { throw new ParsingException("ester formation was mentioned more than once in CAS name!"); } parent = uninvertEster(parent); esterEncountered = true; } else { functionalTerms.add(component); } break; case substituent: seperateWordSubstituents.add(component); break; case full: if (StringTools.endsWithCaseInsensitive(component, "ate") || StringTools.endsWithCaseInsensitive(component, "ite") || StringTools.endsWithCaseInsensitive(component, "ium") || StringTools.endsWithCaseInsensitive(component, "hydrofluoride") || StringTools.endsWithCaseInsensitive(component, "hydrochloride") || StringTools.endsWithCaseInsensitive(component, "hydrobromide") || StringTools.endsWithCaseInsensitive(component, "hydroiodide")) { functionalTerms.add(component); } else if (StringTools.endsWithCaseInsensitive(component, "ic") && c + 1 < componentLen && components[c + 1].equalsIgnoreCase("acid")) { functionalTerms.add(component); functionalTerms.add(components[++c]); } else { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)- A full word was encountered where a substituent or functionalTerm was expected"); } break; default: throw new ParsingException("Unrecognised CAS index name form"); } } else if (parseWords.size() == 2 && firstWordType.equals(WordType.substituent)) { List<ParseTokens> secondParseWordTokens = parseWords.get(1).getParseTokens(); WordType secondWordType = OpsinTools.determineWordType(secondParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < secondParseWordTokens.size(); j++) { if (!secondWordType.equals(OpsinTools.determineWordType(secondParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (secondWordType.equals(WordType.functionalTerm) && matchFunctionalTermAllowingSubstituentPrefix.matcher(parseWords.get(1).getWord()).matches()){ functionalTerms.add(component); } else{ throw new ParsingException("Unrecognised CAS index name form, could have a missing space?"); } } else { throw new ParsingException("Unrecognised CAS index name form"); } } else { if (!matchCasCollectiveIndex.matcher(component).matches()) { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)"); } } } } } StringBuilder casName = new StringBuilder(); for (String prefixFunctionalTerm : seperateWordSubstituents) { casName.append(prefixFunctionalTerm); casName.append(" "); } for (int i = substituents.size() - 1; i >= 0; i--) { casName.append(substituents.get(i)); } casName.append(parent); for (String functionalTerm : functionalTerms) { casName.append(" "); casName.append(functionalTerm); } return casName.toString(); }
CASTools { static String uninvertCASName(String name, ParseRules parseRules) throws ParsingException { List<String> nameComponents = new ArrayList<String>(Arrays.asList(matchCommaSpace.split(name))); List<String> substituents = new ArrayList<String>(); List<String> seperateWordSubstituents = new ArrayList<String>(); List<String> functionalTerms = new ArrayList<String>(); String parent = nameComponents.get(0); String[] parentNameParts = parent.split(" "); if (parentNameParts.length != 1) { if (matchCasCollectiveIndex.matcher(parentNameParts[parentNameParts.length - 1]).matches()) { StringBuilder parentSB = new StringBuilder(); for (int i = 0; i < parentNameParts.length - 1; i++) { parentSB.append(parentNameParts[i]); } parent = parentSB.toString(); parentNameParts = parent.split(" "); } for (int i = 1; i < parentNameParts.length; i++) { if (!matchAcid.matcher(parentNameParts[i]).matches()) { ParseRulesResults results = parseRules.getParses(parentNameParts[i]); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.isEmpty()) { throw new ParsingException("Invalid CAS name. Parent compound was followed by an unexpected term"); } } } } boolean addedBracket = false; boolean esterEncountered = false; for (int i = 1; i < nameComponents.size(); i++) { String nameComponent = nameComponents.get(i); Matcher m = matchCompoundWithPhrase.matcher(nameComponent); boolean compoundWithcomponent = false; if (m.lookingAt()) { nameComponent = nameComponent.substring(m.group().length()); compoundWithcomponent = true; } String[] components = nameComponents.get(i).split(" "); for (int c = 0, componentLen = components.length; c < componentLen; c++) { String component = components[c]; if (compoundWithcomponent) { functionalTerms.add(component); continue; } if (component.endsWith("-")) { Character missingCloseBracket = missingCloseBracketCharIfApplicable(component); if (missingCloseBracket !=null) { if (addedBracket) { throw new ParsingException("Close bracket appears to be missing"); } parent += missingCloseBracket; addedBracket = true; } substituents.add(component); } else { ParseRulesResults results = parseRules.getParses(component); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.size() > 0) { List<ParseWord> parseWords = WordTools.splitIntoParseWords(parseTokens, component); List<ParseTokens> firstParseWordTokens = parseWords.get(0).getParseTokens(); WordType firstWordType = OpsinTools.determineWordType(firstParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < firstParseWordTokens.size(); j++) { if (!firstWordType.equals(OpsinTools.determineWordType(firstParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (parseWords.size() == 1) { switch (firstWordType) { case functionalTerm: if (component.equalsIgnoreCase("ester")) { if (seperateWordSubstituents.size() ==0){ throw new ParsingException("ester encountered but no substituents were specified in potential CAS name!"); } if (esterEncountered) { throw new ParsingException("ester formation was mentioned more than once in CAS name!"); } parent = uninvertEster(parent); esterEncountered = true; } else { functionalTerms.add(component); } break; case substituent: seperateWordSubstituents.add(component); break; case full: if (StringTools.endsWithCaseInsensitive(component, "ate") || StringTools.endsWithCaseInsensitive(component, "ite") || StringTools.endsWithCaseInsensitive(component, "ium") || StringTools.endsWithCaseInsensitive(component, "hydrofluoride") || StringTools.endsWithCaseInsensitive(component, "hydrochloride") || StringTools.endsWithCaseInsensitive(component, "hydrobromide") || StringTools.endsWithCaseInsensitive(component, "hydroiodide")) { functionalTerms.add(component); } else if (StringTools.endsWithCaseInsensitive(component, "ic") && c + 1 < componentLen && components[c + 1].equalsIgnoreCase("acid")) { functionalTerms.add(component); functionalTerms.add(components[++c]); } else { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)- A full word was encountered where a substituent or functionalTerm was expected"); } break; default: throw new ParsingException("Unrecognised CAS index name form"); } } else if (parseWords.size() == 2 && firstWordType.equals(WordType.substituent)) { List<ParseTokens> secondParseWordTokens = parseWords.get(1).getParseTokens(); WordType secondWordType = OpsinTools.determineWordType(secondParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < secondParseWordTokens.size(); j++) { if (!secondWordType.equals(OpsinTools.determineWordType(secondParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (secondWordType.equals(WordType.functionalTerm) && matchFunctionalTermAllowingSubstituentPrefix.matcher(parseWords.get(1).getWord()).matches()){ functionalTerms.add(component); } else{ throw new ParsingException("Unrecognised CAS index name form, could have a missing space?"); } } else { throw new ParsingException("Unrecognised CAS index name form"); } } else { if (!matchCasCollectiveIndex.matcher(component).matches()) { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)"); } } } } } StringBuilder casName = new StringBuilder(); for (String prefixFunctionalTerm : seperateWordSubstituents) { casName.append(prefixFunctionalTerm); casName.append(" "); } for (int i = substituents.size() - 1; i >= 0; i--) { casName.append(substituents.get(i)); } casName.append(parent); for (String functionalTerm : functionalTerms) { casName.append(" "); casName.append(functionalTerm); } return casName.toString(); } }
CASTools { static String uninvertCASName(String name, ParseRules parseRules) throws ParsingException { List<String> nameComponents = new ArrayList<String>(Arrays.asList(matchCommaSpace.split(name))); List<String> substituents = new ArrayList<String>(); List<String> seperateWordSubstituents = new ArrayList<String>(); List<String> functionalTerms = new ArrayList<String>(); String parent = nameComponents.get(0); String[] parentNameParts = parent.split(" "); if (parentNameParts.length != 1) { if (matchCasCollectiveIndex.matcher(parentNameParts[parentNameParts.length - 1]).matches()) { StringBuilder parentSB = new StringBuilder(); for (int i = 0; i < parentNameParts.length - 1; i++) { parentSB.append(parentNameParts[i]); } parent = parentSB.toString(); parentNameParts = parent.split(" "); } for (int i = 1; i < parentNameParts.length; i++) { if (!matchAcid.matcher(parentNameParts[i]).matches()) { ParseRulesResults results = parseRules.getParses(parentNameParts[i]); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.isEmpty()) { throw new ParsingException("Invalid CAS name. Parent compound was followed by an unexpected term"); } } } } boolean addedBracket = false; boolean esterEncountered = false; for (int i = 1; i < nameComponents.size(); i++) { String nameComponent = nameComponents.get(i); Matcher m = matchCompoundWithPhrase.matcher(nameComponent); boolean compoundWithcomponent = false; if (m.lookingAt()) { nameComponent = nameComponent.substring(m.group().length()); compoundWithcomponent = true; } String[] components = nameComponents.get(i).split(" "); for (int c = 0, componentLen = components.length; c < componentLen; c++) { String component = components[c]; if (compoundWithcomponent) { functionalTerms.add(component); continue; } if (component.endsWith("-")) { Character missingCloseBracket = missingCloseBracketCharIfApplicable(component); if (missingCloseBracket !=null) { if (addedBracket) { throw new ParsingException("Close bracket appears to be missing"); } parent += missingCloseBracket; addedBracket = true; } substituents.add(component); } else { ParseRulesResults results = parseRules.getParses(component); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.size() > 0) { List<ParseWord> parseWords = WordTools.splitIntoParseWords(parseTokens, component); List<ParseTokens> firstParseWordTokens = parseWords.get(0).getParseTokens(); WordType firstWordType = OpsinTools.determineWordType(firstParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < firstParseWordTokens.size(); j++) { if (!firstWordType.equals(OpsinTools.determineWordType(firstParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (parseWords.size() == 1) { switch (firstWordType) { case functionalTerm: if (component.equalsIgnoreCase("ester")) { if (seperateWordSubstituents.size() ==0){ throw new ParsingException("ester encountered but no substituents were specified in potential CAS name!"); } if (esterEncountered) { throw new ParsingException("ester formation was mentioned more than once in CAS name!"); } parent = uninvertEster(parent); esterEncountered = true; } else { functionalTerms.add(component); } break; case substituent: seperateWordSubstituents.add(component); break; case full: if (StringTools.endsWithCaseInsensitive(component, "ate") || StringTools.endsWithCaseInsensitive(component, "ite") || StringTools.endsWithCaseInsensitive(component, "ium") || StringTools.endsWithCaseInsensitive(component, "hydrofluoride") || StringTools.endsWithCaseInsensitive(component, "hydrochloride") || StringTools.endsWithCaseInsensitive(component, "hydrobromide") || StringTools.endsWithCaseInsensitive(component, "hydroiodide")) { functionalTerms.add(component); } else if (StringTools.endsWithCaseInsensitive(component, "ic") && c + 1 < componentLen && components[c + 1].equalsIgnoreCase("acid")) { functionalTerms.add(component); functionalTerms.add(components[++c]); } else { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)- A full word was encountered where a substituent or functionalTerm was expected"); } break; default: throw new ParsingException("Unrecognised CAS index name form"); } } else if (parseWords.size() == 2 && firstWordType.equals(WordType.substituent)) { List<ParseTokens> secondParseWordTokens = parseWords.get(1).getParseTokens(); WordType secondWordType = OpsinTools.determineWordType(secondParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < secondParseWordTokens.size(); j++) { if (!secondWordType.equals(OpsinTools.determineWordType(secondParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (secondWordType.equals(WordType.functionalTerm) && matchFunctionalTermAllowingSubstituentPrefix.matcher(parseWords.get(1).getWord()).matches()){ functionalTerms.add(component); } else{ throw new ParsingException("Unrecognised CAS index name form, could have a missing space?"); } } else { throw new ParsingException("Unrecognised CAS index name form"); } } else { if (!matchCasCollectiveIndex.matcher(component).matches()) { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)"); } } } } } StringBuilder casName = new StringBuilder(); for (String prefixFunctionalTerm : seperateWordSubstituents) { casName.append(prefixFunctionalTerm); casName.append(" "); } for (int i = substituents.size() - 1; i >= 0; i--) { casName.append(substituents.get(i)); } casName.append(parent); for (String functionalTerm : functionalTerms) { casName.append(" "); casName.append(functionalTerm); } return casName.toString(); }  }
CASTools { static String uninvertCASName(String name, ParseRules parseRules) throws ParsingException { List<String> nameComponents = new ArrayList<String>(Arrays.asList(matchCommaSpace.split(name))); List<String> substituents = new ArrayList<String>(); List<String> seperateWordSubstituents = new ArrayList<String>(); List<String> functionalTerms = new ArrayList<String>(); String parent = nameComponents.get(0); String[] parentNameParts = parent.split(" "); if (parentNameParts.length != 1) { if (matchCasCollectiveIndex.matcher(parentNameParts[parentNameParts.length - 1]).matches()) { StringBuilder parentSB = new StringBuilder(); for (int i = 0; i < parentNameParts.length - 1; i++) { parentSB.append(parentNameParts[i]); } parent = parentSB.toString(); parentNameParts = parent.split(" "); } for (int i = 1; i < parentNameParts.length; i++) { if (!matchAcid.matcher(parentNameParts[i]).matches()) { ParseRulesResults results = parseRules.getParses(parentNameParts[i]); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.isEmpty()) { throw new ParsingException("Invalid CAS name. Parent compound was followed by an unexpected term"); } } } } boolean addedBracket = false; boolean esterEncountered = false; for (int i = 1; i < nameComponents.size(); i++) { String nameComponent = nameComponents.get(i); Matcher m = matchCompoundWithPhrase.matcher(nameComponent); boolean compoundWithcomponent = false; if (m.lookingAt()) { nameComponent = nameComponent.substring(m.group().length()); compoundWithcomponent = true; } String[] components = nameComponents.get(i).split(" "); for (int c = 0, componentLen = components.length; c < componentLen; c++) { String component = components[c]; if (compoundWithcomponent) { functionalTerms.add(component); continue; } if (component.endsWith("-")) { Character missingCloseBracket = missingCloseBracketCharIfApplicable(component); if (missingCloseBracket !=null) { if (addedBracket) { throw new ParsingException("Close bracket appears to be missing"); } parent += missingCloseBracket; addedBracket = true; } substituents.add(component); } else { ParseRulesResults results = parseRules.getParses(component); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.size() > 0) { List<ParseWord> parseWords = WordTools.splitIntoParseWords(parseTokens, component); List<ParseTokens> firstParseWordTokens = parseWords.get(0).getParseTokens(); WordType firstWordType = OpsinTools.determineWordType(firstParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < firstParseWordTokens.size(); j++) { if (!firstWordType.equals(OpsinTools.determineWordType(firstParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (parseWords.size() == 1) { switch (firstWordType) { case functionalTerm: if (component.equalsIgnoreCase("ester")) { if (seperateWordSubstituents.size() ==0){ throw new ParsingException("ester encountered but no substituents were specified in potential CAS name!"); } if (esterEncountered) { throw new ParsingException("ester formation was mentioned more than once in CAS name!"); } parent = uninvertEster(parent); esterEncountered = true; } else { functionalTerms.add(component); } break; case substituent: seperateWordSubstituents.add(component); break; case full: if (StringTools.endsWithCaseInsensitive(component, "ate") || StringTools.endsWithCaseInsensitive(component, "ite") || StringTools.endsWithCaseInsensitive(component, "ium") || StringTools.endsWithCaseInsensitive(component, "hydrofluoride") || StringTools.endsWithCaseInsensitive(component, "hydrochloride") || StringTools.endsWithCaseInsensitive(component, "hydrobromide") || StringTools.endsWithCaseInsensitive(component, "hydroiodide")) { functionalTerms.add(component); } else if (StringTools.endsWithCaseInsensitive(component, "ic") && c + 1 < componentLen && components[c + 1].equalsIgnoreCase("acid")) { functionalTerms.add(component); functionalTerms.add(components[++c]); } else { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)- A full word was encountered where a substituent or functionalTerm was expected"); } break; default: throw new ParsingException("Unrecognised CAS index name form"); } } else if (parseWords.size() == 2 && firstWordType.equals(WordType.substituent)) { List<ParseTokens> secondParseWordTokens = parseWords.get(1).getParseTokens(); WordType secondWordType = OpsinTools.determineWordType(secondParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < secondParseWordTokens.size(); j++) { if (!secondWordType.equals(OpsinTools.determineWordType(secondParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (secondWordType.equals(WordType.functionalTerm) && matchFunctionalTermAllowingSubstituentPrefix.matcher(parseWords.get(1).getWord()).matches()){ functionalTerms.add(component); } else{ throw new ParsingException("Unrecognised CAS index name form, could have a missing space?"); } } else { throw new ParsingException("Unrecognised CAS index name form"); } } else { if (!matchCasCollectiveIndex.matcher(component).matches()) { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)"); } } } } } StringBuilder casName = new StringBuilder(); for (String prefixFunctionalTerm : seperateWordSubstituents) { casName.append(prefixFunctionalTerm); casName.append(" "); } for (int i = substituents.size() - 1; i >= 0; i--) { casName.append(substituents.get(i)); } casName.append(parent); for (String functionalTerm : functionalTerms) { casName.append(" "); casName.append(functionalTerm); } return casName.toString(); }   }
CASTools { static String uninvertCASName(String name, ParseRules parseRules) throws ParsingException { List<String> nameComponents = new ArrayList<String>(Arrays.asList(matchCommaSpace.split(name))); List<String> substituents = new ArrayList<String>(); List<String> seperateWordSubstituents = new ArrayList<String>(); List<String> functionalTerms = new ArrayList<String>(); String parent = nameComponents.get(0); String[] parentNameParts = parent.split(" "); if (parentNameParts.length != 1) { if (matchCasCollectiveIndex.matcher(parentNameParts[parentNameParts.length - 1]).matches()) { StringBuilder parentSB = new StringBuilder(); for (int i = 0; i < parentNameParts.length - 1; i++) { parentSB.append(parentNameParts[i]); } parent = parentSB.toString(); parentNameParts = parent.split(" "); } for (int i = 1; i < parentNameParts.length; i++) { if (!matchAcid.matcher(parentNameParts[i]).matches()) { ParseRulesResults results = parseRules.getParses(parentNameParts[i]); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.isEmpty()) { throw new ParsingException("Invalid CAS name. Parent compound was followed by an unexpected term"); } } } } boolean addedBracket = false; boolean esterEncountered = false; for (int i = 1; i < nameComponents.size(); i++) { String nameComponent = nameComponents.get(i); Matcher m = matchCompoundWithPhrase.matcher(nameComponent); boolean compoundWithcomponent = false; if (m.lookingAt()) { nameComponent = nameComponent.substring(m.group().length()); compoundWithcomponent = true; } String[] components = nameComponents.get(i).split(" "); for (int c = 0, componentLen = components.length; c < componentLen; c++) { String component = components[c]; if (compoundWithcomponent) { functionalTerms.add(component); continue; } if (component.endsWith("-")) { Character missingCloseBracket = missingCloseBracketCharIfApplicable(component); if (missingCloseBracket !=null) { if (addedBracket) { throw new ParsingException("Close bracket appears to be missing"); } parent += missingCloseBracket; addedBracket = true; } substituents.add(component); } else { ParseRulesResults results = parseRules.getParses(component); List<ParseTokens> parseTokens = results.getParseTokensList(); if (parseTokens.size() > 0) { List<ParseWord> parseWords = WordTools.splitIntoParseWords(parseTokens, component); List<ParseTokens> firstParseWordTokens = parseWords.get(0).getParseTokens(); WordType firstWordType = OpsinTools.determineWordType(firstParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < firstParseWordTokens.size(); j++) { if (!firstWordType.equals(OpsinTools.determineWordType(firstParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (parseWords.size() == 1) { switch (firstWordType) { case functionalTerm: if (component.equalsIgnoreCase("ester")) { if (seperateWordSubstituents.size() ==0){ throw new ParsingException("ester encountered but no substituents were specified in potential CAS name!"); } if (esterEncountered) { throw new ParsingException("ester formation was mentioned more than once in CAS name!"); } parent = uninvertEster(parent); esterEncountered = true; } else { functionalTerms.add(component); } break; case substituent: seperateWordSubstituents.add(component); break; case full: if (StringTools.endsWithCaseInsensitive(component, "ate") || StringTools.endsWithCaseInsensitive(component, "ite") || StringTools.endsWithCaseInsensitive(component, "ium") || StringTools.endsWithCaseInsensitive(component, "hydrofluoride") || StringTools.endsWithCaseInsensitive(component, "hydrochloride") || StringTools.endsWithCaseInsensitive(component, "hydrobromide") || StringTools.endsWithCaseInsensitive(component, "hydroiodide")) { functionalTerms.add(component); } else if (StringTools.endsWithCaseInsensitive(component, "ic") && c + 1 < componentLen && components[c + 1].equalsIgnoreCase("acid")) { functionalTerms.add(component); functionalTerms.add(components[++c]); } else { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)- A full word was encountered where a substituent or functionalTerm was expected"); } break; default: throw new ParsingException("Unrecognised CAS index name form"); } } else if (parseWords.size() == 2 && firstWordType.equals(WordType.substituent)) { List<ParseTokens> secondParseWordTokens = parseWords.get(1).getParseTokens(); WordType secondWordType = OpsinTools.determineWordType(secondParseWordTokens.get(0).getAnnotations()); for (int j = 1; j < secondParseWordTokens.size(); j++) { if (!secondWordType.equals(OpsinTools.determineWordType(secondParseWordTokens.get(j).getAnnotations()))) { throw new ParsingException(component + "can be interpreted in multiple ways. For the sake of precision OPSIN has decided not to process this as a CAS name"); } } if (secondWordType.equals(WordType.functionalTerm) && matchFunctionalTermAllowingSubstituentPrefix.matcher(parseWords.get(1).getWord()).matches()){ functionalTerms.add(component); } else{ throw new ParsingException("Unrecognised CAS index name form, could have a missing space?"); } } else { throw new ParsingException("Unrecognised CAS index name form"); } } else { if (!matchCasCollectiveIndex.matcher(component).matches()) { throw new ParsingException("Unable to interpret: " + component + " (as part of a CAS index name)"); } } } } } StringBuilder casName = new StringBuilder(); for (String prefixFunctionalTerm : seperateWordSubstituents) { casName.append(prefixFunctionalTerm); casName.append(" "); } for (int i = substituents.size() - 1; i >= 0; i--) { casName.append(substituents.get(i)); } casName.append(parent); for (String functionalTerm : functionalTerms) { casName.append(" "); casName.append(functionalTerm); } return casName.toString(); }    }