/** * Copyright © 2012 Akiban Technologies, Inc. All rights * reserved. * * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * This program may also be available under different license terms. * For more information, see www.akiban.com or contact * licensing@akiban.com. * * Contributors: * Akiban Technologies, Inc. */ package com.akiban.sql; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class CompareWithoutHashes { public static final String HASH_REGEX = "[\\p{Alnum}]*\\@[\\p{XDigit}]+"; private Pattern pattern; private Map<String,String> equivalences; public CompareWithoutHashes() { this(HASH_REGEX); } public CompareWithoutHashes(String regex) { this.pattern = Pattern.compile(regex); this.equivalences = new HashMap<String,String>(); } public boolean match(Reader r1, Reader r2) throws IOException { BufferedReader br1 = new BufferedReader(r1); BufferedReader br2 = new BufferedReader(r2); while (true) { String l1 = br1.readLine(); String l2 = br2.readLine(); if (l1 == null) { if (l2 == null) break; l1 = ""; } else if (l2 == null) l2 = ""; if (!match(l1, l2)) return false; } return true; } public boolean match(String s1, String s2) { String[][] ha1 = findHashes(s1); String[][] ha2 = findHashes(s2); if (ha1.length != ha2.length) return false; for (int i = 0; i < ha1.length; i++) { if (!ha1[i][0].equals(ha2[i][0])) // checks that the part before the hash matches return false; String oh2 = equivalences.put(ha1[i][1], ha2[i][1]); if ((oh2 != null) && !oh2.equals(ha2[i][1])) return false; } // It's possible that equivalences swaps two matches, so need intermediate. for (int i = 0; i < ha1.length; i++) { s1 = s1.replace(ha1[i][1], "%!" + i + "!%"); } for (int i = 0; i < ha1.length; i++) { s1 = s1.replace("%!" + i + "!%", ha2[i][1]); } return s1.equals(s2); } protected String[][] findHashes(String s) { Matcher matcher = pattern.matcher(s); List<String[]> matches = new ArrayList<String[]>(); while (matcher.find()) { String hash = matcher.group(); String[] match = { hash.substring(0,hash.indexOf('@')), hash }; matches.add(match); } return matches.toArray(new String[matches.size()][2]); } public String converter(String s1, String s2) { String[][] ha1 = findHashes(s1); String[][] ha2 = findHashes(s2); int i1 = 0; for (int i2 = 0; i1 < ha1.length && i2 < ha2.length; i1++) { if (ha1[i1][0].equals(ha2[i2][0])) s1 = s1.replace(ha1[i1][1], "%!" + i2 + "!%"); else { adjust: for (int ia1 = i1; ia1 < Math.min(i1+2,ha1.length); ia1++) { for (int ia2 = i2; ia2 < Math.min(i2+2,ha2.length); ia2++) { if (ha1[ia1][0].equals(ha2[ia2][0])) { s1 = s1.replace(ha1[ia1][1], "%!" + ia2 + "!%"); i1 = ia1; i2 = ia2; break adjust; } } } } i2++; } for (int i = 0; i < ha2.length; i++) { s1 = s1.replace("%!" + i + "!%", ha2[i][1]); } return s1; } }