001package gudusoft.gsqlparser.slpc.adapter; 002 003import gudusoft.gsqlparser.dlineage.dataflow.model.xml.dataflow; 004import gudusoft.gsqlparser.slpc.json.SlpcJson; 005 006import java.nio.charset.StandardCharsets; 007import java.security.MessageDigest; 008import java.security.NoSuchAlgorithmException; 009import java.util.Arrays; 010 011/** 012 * Builds SLPC twice from the exact same completed dataflow instance and binds 013 * the caller's already-produced legacy output to the comparison report. 014 */ 015public final class LegacyDualBuildHarness { 016 private final LegacyDlineageAdapter adapter; 017 018 public LegacyDualBuildHarness() { this(new LegacyDlineageAdapter()); } 019 public LegacyDualBuildHarness(LegacyDlineageAdapter adapter) { this.adapter = adapter; } 020 021 public LegacyDualBuildResult compare(dataflow completedResult, String legacyOutput, 022 LegacyAdapterContext context) { 023 if (legacyOutput == null) throw new IllegalArgumentException("legacy output from the same analysis must not be null"); 024 LegacyAdaptation first = adapter.adapt(completedResult, context); 025 LegacyAdaptation second = adapter.adapt(completedResult, context); 026 byte[] firstBytes = SlpcJson.canonicalBytes(first.document()); 027 byte[] secondBytes = SlpcJson.canonicalBytes(second.document()); 028 DeterminismReport report = new DeterminismReport(Arrays.equals(firstBytes, secondBytes), sha256(firstBytes), 029 sha256(secondBytes), sha256(legacyOutput.getBytes(StandardCharsets.UTF_8))); 030 return new LegacyDualBuildResult(first, report); 031 } 032 033 private static String sha256(byte[] bytes) { 034 try { 035 byte[] digest = MessageDigest.getInstance("SHA-256").digest(bytes); 036 StringBuilder result = new StringBuilder(); 037 for (byte value : digest) result.append(String.format("%02x", value & 255)); 038 return result.toString(); 039 } catch (NoSuchAlgorithmException impossible) { throw new IllegalStateException(impossible); } 040 } 041}