diff --git a/merge_sort_java/pom.xml b/merge_sort_java/pom.xml new file mode 100644 index 0000000..edb39b4 --- /dev/null +++ b/merge_sort_java/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.mergesort + merge-sort-example + 1.0-SNAPSHOT + jar + + Merge Sort Example + Java rebuild of COBOL merge_sort_test.cbl - Testing sort and merge on customer test data + + + 17 + 17 + UTF-8 + + + + + junit + junit + 4.13.2 + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + com.mergesort.MergeSortExample + + + + + + + diff --git a/merge_sort_java/src/main/java/com/mergesort/CustomerRecord.java b/merge_sort_java/src/main/java/com/mergesort/CustomerRecord.java new file mode 100644 index 0000000..76fecf6 --- /dev/null +++ b/merge_sort_java/src/main/java/com/mergesort/CustomerRecord.java @@ -0,0 +1,91 @@ +package com.mergesort; + +import java.util.Comparator; + +public class CustomerRecord { + + public static final Comparator BY_CUSTOMER_ID_ASC = + Comparator.comparingInt(CustomerRecord::getCustomerId); + + public static final Comparator BY_CONTRACT_ID_DESC = + Comparator.comparingInt(CustomerRecord::getContractId).reversed(); + + private int customerId; + private String lastName; + private String firstName; + private int contractId; + private String comment; + + public CustomerRecord(int customerId, String lastName, String firstName, + int contractId, String comment) { + this.customerId = customerId; + this.lastName = lastName; + this.firstName = firstName; + this.contractId = contractId; + this.comment = comment; + } + + public int getCustomerId() { + return customerId; + } + + public String getLastName() { + return lastName; + } + + public String getFirstName() { + return firstName; + } + + public int getContractId() { + return contractId; + } + + public String getComment() { + return comment; + } + + public String toFileString() { + return String.format("%05d%-50s%-50s%05d%-25s", + customerId, lastName, firstName, contractId, comment); + } + + public static CustomerRecord fromFileString(String line) { + if (line.length() < 135) { + line = String.format("%-135s", line); + } + int id = Integer.parseInt(line.substring(0, 5).trim()); + String last = line.substring(5, 55).trim(); + String first = line.substring(55, 105).trim(); + int contract = Integer.parseInt(line.substring(105, 110).trim()); + String cmt = line.substring(110, 135).trim(); + return new CustomerRecord(id, last, first, contract, cmt); + } + + @Override + public String toString() { + return toFileString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomerRecord that = (CustomerRecord) o; + return customerId == that.customerId + && contractId == that.contractId + && lastName.equals(that.lastName) + && firstName.equals(that.firstName) + && comment.equals(that.comment); + } + + @Override + public int hashCode() { + int result = customerId; + result = 31 * result + lastName.hashCode(); + result = 31 * result + firstName.hashCode(); + result = 31 * result + contractId; + result = 31 * result + comment.hashCode(); + return result; + } +} diff --git a/merge_sort_java/src/main/java/com/mergesort/MergeSortExample.java b/merge_sort_java/src/main/java/com/mergesort/MergeSortExample.java new file mode 100644 index 0000000..6933794 --- /dev/null +++ b/merge_sort_java/src/main/java/com/mergesort/MergeSortExample.java @@ -0,0 +1,107 @@ +package com.mergesort; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public class MergeSortExample { + + private final Path workDir; + + public MergeSortExample(Path workDir) { + this.workDir = workDir; + } + + public static void main(String[] args) throws IOException { + Path dir = Path.of(System.getProperty("user.dir")); + MergeSortExample app = new MergeSortExample(dir); + app.run(); + } + + public void run() throws IOException { + createTestData(); + mergeAndDisplayFiles(); + sortAndDisplayFile(); + System.out.println("Done."); + } + + void createTestData() throws IOException { + System.out.println("Creating test data files..."); + + List eastRecords = List.of( + new CustomerRecord(1, "last-1", "first-1", 5423, "comment-1"), + new CustomerRecord(5, "last-5", "first-5", 12323, "comment-5"), + new CustomerRecord(10, "last-10", "first-10", 653, "comment-10"), + new CustomerRecord(50, "last-50", "first-50", 5050, "comment-50"), + new CustomerRecord(25, "last-25", "first-25", 7725, "comment-25"), + new CustomerRecord(75, "last-75", "first-75", 1175, "comment-75") + ); + writeRecords(workDir.resolve("test-file-1.txt"), eastRecords); + + List westRecords = List.of( + new CustomerRecord(999, "last-999", "first-999", 1610, "comment-99"), + new CustomerRecord(3, "last-03", "first-03", 3331, "comment-03"), + new CustomerRecord(30, "last-30", "first-30", 8765, "comment-30"), + new CustomerRecord(85, "last-85", "first-85", 4567, "comment-85"), + new CustomerRecord(24, "last-24", "first-24", 247, "comment-24") + ); + writeRecords(workDir.resolve("test-file-2.txt"), westRecords); + } + + void mergeAndDisplayFiles() throws IOException { + System.out.println("Merging and sorting files..."); + + List file1Records = readRecords(workDir.resolve("test-file-1.txt")); + List file2Records = readRecords(workDir.resolve("test-file-2.txt")); + + List merged = new ArrayList<>(); + merged.addAll(file1Records); + merged.addAll(file2Records); + merged.sort(CustomerRecord.BY_CUSTOMER_ID_ASC); + + writeRecords(workDir.resolve("merge-output.txt"), merged); + + for (CustomerRecord record : merged) { + System.out.println(record); + } + } + + void sortAndDisplayFile() throws IOException { + System.out.println("Sorting merged file on descending contract id...."); + + List mergedRecords = readRecords(workDir.resolve("merge-output.txt")); + mergedRecords.sort(CustomerRecord.BY_CONTRACT_ID_DESC); + + writeRecords(workDir.resolve("sorted-contract-id.txt"), mergedRecords); + + for (CustomerRecord record : mergedRecords) { + System.out.println(record); + } + } + + List readRecords(Path file) throws IOException { + List records = new ArrayList<>(); + try (BufferedReader reader = Files.newBufferedReader(file)) { + String line; + while ((line = reader.readLine()) != null) { + if (!line.isBlank()) { + records.add(CustomerRecord.fromFileString(line)); + } + } + } + return records; + } + + void writeRecords(Path file, List records) throws IOException { + try (BufferedWriter writer = Files.newBufferedWriter(file)) { + for (CustomerRecord record : records) { + writer.write(record.toFileString()); + writer.newLine(); + } + } + } +} diff --git a/merge_sort_java/src/test/java/com/mergesort/MergeSortExampleTest.java b/merge_sort_java/src/test/java/com/mergesort/MergeSortExampleTest.java new file mode 100644 index 0000000..d740fe1 --- /dev/null +++ b/merge_sort_java/src/test/java/com/mergesort/MergeSortExampleTest.java @@ -0,0 +1,116 @@ +package com.mergesort; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class MergeSortExampleTest { + + private Path tempDir; + private MergeSortExample app; + + @Before + public void setUp() throws IOException { + tempDir = Files.createTempDirectory("merge-sort-test"); + app = new MergeSortExample(tempDir); + } + + @After + public void tearDown() throws IOException { + Files.walk(tempDir) + .sorted(java.util.Comparator.reverseOrder()) + .forEach(p -> { + try { Files.deleteIfExists(p); } catch (IOException ignored) {} + }); + } + + @Test + public void testCreateTestData() throws IOException { + app.createTestData(); + + Path file1 = tempDir.resolve("test-file-1.txt"); + Path file2 = tempDir.resolve("test-file-2.txt"); + assertTrue("test-file-1.txt should exist", Files.exists(file1)); + assertTrue("test-file-2.txt should exist", Files.exists(file2)); + + List lines1 = Files.readAllLines(file1); + assertEquals("East file should have 6 records", 6, lines1.size()); + + List lines2 = Files.readAllLines(file2); + assertEquals("West file should have 5 records", 5, lines2.size()); + } + + @Test + public void testMergeAndDisplayFiles() throws IOException { + app.createTestData(); + app.mergeAndDisplayFiles(); + + Path mergedFile = tempDir.resolve("merge-output.txt"); + assertTrue("merge-output.txt should exist", Files.exists(mergedFile)); + + List records = app.readRecords(mergedFile); + assertEquals("Merged file should have 11 records", 11, records.size()); + + for (int i = 1; i < records.size(); i++) { + assertTrue("Records should be sorted by customer ID ascending", + records.get(i).getCustomerId() >= records.get(i - 1).getCustomerId()); + } + + assertEquals(1, records.get(0).getCustomerId()); + assertEquals(3, records.get(1).getCustomerId()); + assertEquals(5, records.get(2).getCustomerId()); + assertEquals(999, records.get(10).getCustomerId()); + } + + @Test + public void testSortAndDisplayFile() throws IOException { + app.createTestData(); + app.mergeAndDisplayFiles(); + app.sortAndDisplayFile(); + + Path sortedFile = tempDir.resolve("sorted-contract-id.txt"); + assertTrue("sorted-contract-id.txt should exist", Files.exists(sortedFile)); + + List records = app.readRecords(sortedFile); + assertEquals("Sorted file should have 11 records", 11, records.size()); + + for (int i = 1; i < records.size(); i++) { + assertTrue("Records should be sorted by contract ID descending", + records.get(i).getContractId() <= records.get(i - 1).getContractId()); + } + + assertEquals(12323, records.get(0).getContractId()); + assertEquals(247, records.get(10).getContractId()); + } + + @Test + public void testCustomerRecordRoundTrip() { + CustomerRecord original = new CustomerRecord(42, "Smith", "John", 12345, "test-comment"); + String fileString = original.toFileString(); + CustomerRecord parsed = CustomerRecord.fromFileString(fileString); + + assertEquals(original.getCustomerId(), parsed.getCustomerId()); + assertEquals(original.getLastName(), parsed.getLastName()); + assertEquals(original.getFirstName(), parsed.getFirstName()); + assertEquals(original.getContractId(), parsed.getContractId()); + assertEquals(original.getComment(), parsed.getComment()); + } + + @Test + public void testFullRun() throws IOException { + app.run(); + + assertTrue(Files.exists(tempDir.resolve("test-file-1.txt"))); + assertTrue(Files.exists(tempDir.resolve("test-file-2.txt"))); + assertTrue(Files.exists(tempDir.resolve("merge-output.txt"))); + assertTrue(Files.exists(tempDir.resolve("sorted-contract-id.txt"))); + } +}