/******************************************************************************* * Copyright © 2012-2015 eBay Software Foundation * This program is dual licensed under the MIT and Apache 2.0 licenses. * Please see LICENSE for more information. *******************************************************************************/ package com.ebay.jetstream.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * * */ public class FuzzyMatcher { public static interface Consumer { /** * Take the original string, and check whether it begins with the matcher * @param originalString * @return the remaining string after match */ String consume(String originalString) throws PatternNotMatchException; } public static class ExactMatchConsumer implements Consumer { private String matcherString; public ExactMatchConsumer(String matcherString) { this.matcherString = matcherString; } public String consume(String originalString) throws PatternNotMatchException { if (originalString.startsWith(matcherString)) { return originalString.substring(matcherString.length()); } else { throw new PatternNotMatchException(); } } public String toString() { return "Exact:" + matcherString; } } public static class RegExMatchConsumer implements Consumer { private String matcherString; public RegExMatchConsumer(String matcherString) { this.matcherString = matcherString; } public String consume(String originalString) throws PatternNotMatchException { Pattern pattern = Pattern.compile(matcherString); Matcher matcher = pattern.matcher(originalString); if (matcher.find()) { if (matcher.start() == 0) { return originalString.substring(matcher.end()); } } throw new PatternNotMatchException(); } public String toString() { return "Regex:" + matcherString; } } private final static String regexStartPattern = "\\{\\{"; private final static String regexEndPattern = "\\}\\}"; private List<Consumer> listOfConsumers = new ArrayList<Consumer>(); public FuzzyMatcher() { } public FuzzyMatcher(String fileContainingExpectedString) { setExpectation(FileUtils.readFileOrNull(fileContainingExpectedString)); } public void setExpectation(String expectedString) { Pattern startPattern = Pattern.compile(regexStartPattern); Pattern endPattern = Pattern.compile(regexEndPattern); String remainingString = expectedString; while (true) { Matcher matcher1 = startPattern.matcher(remainingString); if (matcher1.find()) { listOfConsumers.add(new ExactMatchConsumer(remainingString.substring(0, matcher1.start()))); String cutHead = remainingString.substring(matcher1.end()); Matcher matcher2 = endPattern.matcher(cutHead); if (matcher2.find()) { String regex = cutHead.substring(0, matcher2.start()); listOfConsumers.add(new RegExMatchConsumer(regex)); remainingString = cutHead.substring(matcher2.end()); continue; } } listOfConsumers.add(new ExactMatchConsumer(remainingString)); break; } } public boolean match(String originalString) { String remainingString = originalString; Iterator<Consumer> it = listOfConsumers.iterator(); while (it.hasNext() && remainingString.length() > 0) { Consumer consumer = it.next(); try { remainingString = consumer.consume(remainingString); } catch (PatternNotMatchException e) { return false; } } return true; } public boolean matchFile(String filename) { String content = FileUtils.readFileOrNull(filename); return match(content); } public String replace(String originalString, String[] regexArray) { String resultString = originalString; for (String regex : regexArray) { String replacedForm = "{{" + regex.replace("\\", "\\\\") + "}}"; resultString = resultString.replaceAll(regex, replacedForm); } return resultString; } }