package edu.stanford.nlp.util; import edu.stanford.nlp.ling.CoreAnnotations; import edu.stanford.nlp.ling.CoreLabel; import java.util.*; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * A simple class with a variety of acronym matching utilities. * * You're probably looking for the method {@link AcronymMatcher#isAcronym(String, List)}. * * @author Gabor Angeli */ @SuppressWarnings("Convert2Diamond") public class AcronymMatcher { private static final Pattern discardPattern = Pattern.compile("[-._]"); /** A set of words that should be considered stopwords for the acronym matcher */ private static final Set<String> STOPWORDS = Collections.unmodifiableSet(new HashSet<String>(){{ add("'d"); add("'ll"); add("'re"); add("'s"); add("'t"); add("'ve"); add("n't"); add("a"); add("about"); add("above"); add("after"); add("again"); add("against"); add("all"); add("am"); add("an"); add("and"); add("any"); add("are"); add("as"); add("at"); add("be"); add("because"); add("been"); add("before"); add("being"); add("below"); add("between"); add("both"); add("but"); add("by"); add("cannot"); add("could"); add("did"); add("do"); add("does"); add("doing"); add("down"); add("during"); add("each"); add("few"); add("for"); add("from"); add("further"); add("had"); add("has"); add("have"); add("having"); add("he"); add("her"); add("here"); add("hers"); add("herself"); add("him"); add("himself"); add("his"); add("how"); add("i"); add("if"); add("in"); add("into"); add("is"); add("it"); add("its"); add("itself"); add("me"); add("more"); add("most"); add("my"); add("myself"); add("no"); add("nor"); add("not"); add("of"); add("off"); add("on"); add("once"); add("only"); add("or"); add("other"); add("ought"); add("our"); add("ours"); add("ourselves"); add("out"); add("over"); add("own"); add("same"); add("she"); add("should"); add("so"); add("some"); add("such"); add("than"); add("their"); add("theirs"); add("them"); add("themselves"); add("the"); add("then"); add("there"); add("these"); add("they"); add("this"); add("those"); add("through"); add("to"); add("too"); add("under"); add("until"); add("up"); add("very"); add("was"); add("we"); add("were"); add("what"); add("when"); add("where"); add("which"); add("while"); add("who"); add("whom"); add("why"); add("with"); add("would"); add("you"); add("your"); add("yours"); add("yourself"); add("yourselves"); add("de"); add("del"); add("di"); add("y"); add("corporation"); add("corp"); add("corp."); add("co"); add("llc"); add("inc"); add("inc."); add("ltd"); add("ltd."); add("llp"); add("llp."); add("plc"); add("plc."); add("&"); add(","); add("-"); }}); private static List<String> getTokenStrs(List<CoreLabel> tokens) { List<String> mainTokenStrs = new ArrayList<String>(tokens.size()); for (CoreLabel token:tokens) { String text = token.get(CoreAnnotations.TextAnnotation.class); mainTokenStrs.add(text); } return mainTokenStrs; } private static List<String> getMainTokenStrs(List<CoreLabel> tokens) { List<String> mainTokenStrs = new ArrayList<String>(tokens.size()); for (CoreLabel token:tokens) { String text = token.get(CoreAnnotations.TextAnnotation.class); if (!text.isEmpty() && ( text.length() >= 4 || Character.isUpperCase(text.charAt(0))) ) { mainTokenStrs.add(text); } } return mainTokenStrs; } private static List<String> getMainTokenStrs(String[] tokens) { List<String> mainTokenStrs = new ArrayList<String>(tokens.length); for (String text:tokens) { if ( !text.isEmpty() && ( text.length() >= 4 || Character.isUpperCase(text.charAt(0)) ) ) { mainTokenStrs.add(text); } } return mainTokenStrs; } public static List<String> getMainStrs(List<String> tokens) { List<String> mainTokenStrs = new ArrayList<String>(tokens.size()); mainTokenStrs.addAll(tokens.stream().filter(text -> !text.isEmpty() && (text.length() >= 4 || Character.isUpperCase(text.charAt(0)))).collect(Collectors.toList())); return mainTokenStrs; } public static boolean isAcronym(String str, String[] tokens) { return isAcronymImpl(str, Arrays.asList(tokens)); } // Public static utility methods public static boolean isAcronymImpl(String str, List<String> tokens) { // Remove some words from the candidate acronym str = discardPattern.matcher(str).replaceAll(""); // Remove stopwords if we need to if (str.length() != tokens.size()) { tokens = tokens.stream().filter(x -> !STOPWORDS.contains(x.toLowerCase())).collect(Collectors.toList()); } // Run the matcher if (str.length() == tokens.size()) { for (int i = 0; i < str.length(); i++) { char ch = Character.toUpperCase(str.charAt(i)); if ( !tokens.get(i).isEmpty() && Character.toUpperCase(tokens.get(i).charAt(0)) != ch ) { return false; } } return true; } else { return false; } } public static boolean isAcronym(String str, List<?> tokens) { List<String> strs = new ArrayList<String>(tokens.size()); for (Object tok : tokens) { if (tok instanceof String) { strs.add(tok.toString()); } else if (tok instanceof CoreMap) { strs.add(((CoreMap) tok).get(CoreAnnotations.TextAnnotation.class)); } else { strs.add(tok.toString()); } } return isAcronymImpl(str, strs); } /** * Returns true if either chunk1 or chunk2 is acronym of the other * @return true if either chunk1 or chunk2 is acronym of the other */ public static boolean isAcronym(CoreMap chunk1, CoreMap chunk2) { String text1 = chunk1.get(CoreAnnotations.TextAnnotation.class); String text2 = chunk2.get(CoreAnnotations.TextAnnotation.class); if (text1.length() <= 1 || text2.length() <= 1) { return false; } List<String> tokenStrs1 = getTokenStrs(chunk1.get(CoreAnnotations.TokensAnnotation.class)); List<String> tokenStrs2 = getTokenStrs(chunk2.get(CoreAnnotations.TokensAnnotation.class)); boolean isAcro = isAcronymImpl(text1, tokenStrs2) || isAcronymImpl(text2, tokenStrs1); if (!isAcro) { tokenStrs1 = getMainTokenStrs(chunk1.get(CoreAnnotations.TokensAnnotation.class)); tokenStrs2 = getMainTokenStrs(chunk2.get(CoreAnnotations.TokensAnnotation.class)); isAcro = isAcronymImpl(text1, tokenStrs2) || isAcronymImpl(text2, tokenStrs1); } return isAcro; } /** @see AcronymMatcher#isAcronym(edu.stanford.nlp.util.CoreMap, edu.stanford.nlp.util.CoreMap) */ public static boolean isAcronym(String[] chunk1, String[] chunk2) { String text1 = StringUtils.join(chunk1); String text2 = StringUtils.join(chunk2); if (text1.length() <= 1 || text2.length() <= 1) { return false; } List<String> tokenStrs1 = Arrays.asList(chunk1); List<String> tokenStrs2 = Arrays.asList(chunk2); boolean isAcro = isAcronymImpl(text1, tokenStrs2) || isAcronymImpl(text2, tokenStrs1); if (!isAcro) { tokenStrs1 = getMainTokenStrs(chunk1); tokenStrs2 = getMainTokenStrs(chunk2); isAcro = isAcronymImpl(text1, tokenStrs2) || isAcronymImpl(text2, tokenStrs1); } return isAcro; } public static boolean isFancyAcronym(String[] chunk1, String[] chunk2) { String text1 = StringUtils.join(chunk1); String text2 = StringUtils.join(chunk2); if (text1.length() <= 1 || text2.length() <= 1) { return false; } List<String> tokenStrs1 = Arrays.asList(chunk1); List<String> tokenStrs2 = Arrays.asList(chunk2); return isFancyAcronymImpl(text1, tokenStrs2) || isFancyAcronymImpl(text2, tokenStrs1); } public static boolean isFancyAcronymImpl(String str, List<String> tokens) { str = discardPattern.matcher(str).replaceAll(""); String text = StringUtils.join(tokens); int prev_index = 0; for(int i=0; i < str.length(); i++) { char ch = str.charAt(i); if(text.indexOf(ch) != -1) { prev_index = text.indexOf(ch, prev_index); if(prev_index == -1) { return false; } } else { return false; } } return true; } }