basic-lib/src/main/java/com/streamsets/pipeline/lib/fuzzy/FuzzyMatch.java
public static int getRatio(String s1, String s2) {

    if (s1.length() >= s2.length()) {
      // We need to swap s1 and s2
      String temp = s2;
      s2 = s1;
      s1 = temp;
    }

    // Get alpha numeric characters
    Set<String> set1 = tokenizeString(escapeString(s1));
    Set<String> set2 = tokenizeString(escapeString(s2));

    SetView<String> intersection = Sets.intersection(set1, set2);

    TreeSet<String> sortedIntersection = Sets.newTreeSet(intersection);

    if (LOG.isTraceEnabled()) {
      StringBuilder sortedSb = new StringBuilder();
      for (String s : sortedIntersection) {
        sortedSb.append(s).append(" ");
      }
      LOG.trace("Sorted intersection --> {}", sortedSb.toString());
    }

    // Find out difference of sets set1 and intersection of set1,set2
    SetView<String> restOfSet1 = Sets.symmetricDifference(set1, intersection);

    // Sort it
    TreeSet<String> sortedRestOfSet1 = Sets.newTreeSet(restOfSet1);

    SetView<String> restOfSet2 = Sets.symmetricDifference(set2, intersection);
    TreeSet<String> sortedRestOfSet2 = Sets.newTreeSet(restOfSet2);

    if (LOG.isTraceEnabled()) {
      StringBuilder sb1 = new StringBuilder();
      for (String s : sortedRestOfSet1) {
        sb1.append(s).append(" ");
      }
      LOG.trace("Sorted rest of 1 --> {}", sb1.toString());

      StringBuilder sb2 = new StringBuilder();
      for (String s : sortedRestOfSet1) {
        sb2.append(s).append(" ");
      }
      LOG.trace("Sorted rest of 2 --> {}", sb2.toString());
    }

    StringBuilder t0Builder = new StringBuilder("");
    StringBuilder t1Builder = new StringBuilder("");
    StringBuilder t2Builder = new StringBuilder("");

    for (String s : sortedIntersection) {
      t0Builder.append(" ").append(s);
    }
    String t0 = t0Builder.toString().trim();

    Set<String> setT1 = Sets.union(sortedIntersection, sortedRestOfSet1);
    for (String s : setT1) {
      t1Builder.append(" ").append(s);
    }
    String t1 = t1Builder.toString().trim();

    Set<String> setT2 = Sets.union(intersection, sortedRestOfSet2);
    for (String s : setT2) {
      t2Builder.append(" ").append(s);
    }

    String t2 = t2Builder.toString().trim();

    int amt1 = calculateLevenshteinDistance(t0, t1);
    int amt2 = calculateLevenshteinDistance(t0, t2);
    int amt3 = calculateLevenshteinDistance(t1, t2);

    LOG.trace("t0 = {} --> {}", t0, amt1);
    LOG.trace("t1 = {} --> {}", t1, amt2);
    LOG.trace("t2 = {} --> {}", t2, amt3);

    return Math.max(Math.max(amt1, amt2), amt3);
  }
public static int getRatio(String s1, String s2) {

    if (s1.length() >= s2.length()) {
      // We need to swap s1 and s2
      String temp = s2;
      s2 = s1;
      s1 = temp;
    }

    // Get alpha numeric characters
    Set<String> set1 = tokenizeString(escapeString(s1));
    Set<String> set2 = tokenizeString(escapeString(s2));

    SetView<String> intersection = Sets.intersection(set1, set2);

    TreeSet<String> sortedIntersection = Sets.newTreeSet(intersection);

    if (LOG.isTraceEnabled()) {
      StringBuilder sortedSb = new StringBuilder();
      for (String s : sortedIntersection) {
        sortedSb.append(s).append(" ");
      }
      LOG.trace("Sorted intersection --> {}", sortedSb.toString());
    }

    // Find out difference of sets set1 and intersection of set1,set2
    SetView<String> restOfSet1 = Sets.symmetricDifference(set1, intersection);

    // Sort it
    TreeSet<String> sortedRestOfSet1 = Sets.newTreeSet(restOfSet1);

    SetView<String> restOfSet2 = Sets.symmetricDifference(set2, intersection);
    TreeSet<String> sortedRestOfSet2 = Sets.newTreeSet(restOfSet2);

    if (LOG.isTraceEnabled()) {
      StringBuilder sb1 = new StringBuilder();
      for (String s : sortedRestOfSet1) {
        sb1.append(s).append(" ");
      }
      LOG.trace("Sorted rest of 1 --> {}", sb1.toString());

      StringBuilder sb2 = new StringBuilder();
      for (String s : sortedRestOfSet1) {
        sb2.append(s).append(" ");
      }
      LOG.trace("Sorted rest of 2 --> {}", sb2.toString());
    }

    StringBuilder t0Builder = new StringBuilder("");
    StringBuilder t1Builder = new StringBuilder("");
    StringBuilder t2Builder = new StringBuilder("");

    for (String s : sortedIntersection) {
      t0Builder.append(" ").append(s);
    }
    String t0 = t0Builder.toString().trim();

    Set<String> setT1 = Sets.union(sortedIntersection, sortedRestOfSet1);
    for (String s : setT1) {
      t1Builder.append(" ").append(s);
    }
    String t1 = t1Builder.toString().trim();

    Set<String> setT2 = Sets.union(intersection, sortedRestOfSet2);
    for (String s : setT2) {
      t2Builder.append(" ").append(s);
    }

    String t2 = t2Builder.toString().trim();

    int amt1 = calculateLevenshteinDistance(t0, t1);
    int amt2 = calculateLevenshteinDistance(t0, t2);
    int amt3 = calculateLevenshteinDistance(t1, t2);

    LOG.trace("t0 = {} --> {}", t0, amt1);
    LOG.trace("t1 = {} --> {}", t1, amt2);
    LOG.trace("t2 = {} --> {}", t2, amt3);

    return Math.max(Math.max(amt1, amt2), amt3);
  }
/*
t0 = [SORTED_INTERSECTION]
t1 = [SORTED_INTERSECTION] + [SORTED_REST_OF_STRING1]
t2 = [SORTED_INTERSECTION] + [SORTED_REST_OF_STRING2]

outcome = max(t0,t1,t2)