Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions merge_sort_java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.mergesort</groupId>
<artifactId>merge-sort-example</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Merge Sort Example</name>
<description>Java rebuild of COBOL merge_sort_test.cbl - Testing sort and merge on customer test data</description>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.mergesort.MergeSortExample</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
91 changes: 91 additions & 0 deletions merge_sort_java/src/main/java/com/mergesort/CustomerRecord.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.mergesort;

import java.util.Comparator;

public class CustomerRecord {

public static final Comparator<CustomerRecord> BY_CUSTOMER_ID_ASC =
Comparator.comparingInt(CustomerRecord::getCustomerId);

public static final Comparator<CustomerRecord> 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;
}
}
107 changes: 107 additions & 0 deletions merge_sort_java/src/main/java/com/mergesort/MergeSortExample.java
Original file line number Diff line number Diff line change
@@ -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<CustomerRecord> 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<CustomerRecord> 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<CustomerRecord> file1Records = readRecords(workDir.resolve("test-file-1.txt"));
List<CustomerRecord> file2Records = readRecords(workDir.resolve("test-file-2.txt"));

List<CustomerRecord> 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<CustomerRecord> 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<CustomerRecord> readRecords(Path file) throws IOException {
List<CustomerRecord> 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<CustomerRecord> records) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(file)) {
for (CustomerRecord record : records) {
writer.write(record.toFileString());
writer.newLine();
}
}
}
}
116 changes: 116 additions & 0 deletions merge_sort_java/src/test/java/com/mergesort/MergeSortExampleTest.java
Original file line number Diff line number Diff line change
@@ -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<String> lines1 = Files.readAllLines(file1);
assertEquals("East file should have 6 records", 6, lines1.size());

List<String> 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<CustomerRecord> 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<CustomerRecord> 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")));
}
}