Create a Java GUI application that will capture the commission earned by an estate agent for the

sale of a property. The application must capture all the required input and display the estate
agent commission report.

On the form, create one combo box for the estate agent location. The estate agent
locations include Cape Town, Durban, and Pretoria. You are also required to create
three text fields to capture the estate agent name, property price, and commission
percentage. Also, create a text area to display the estate agent report.

A menu system is required for the user to interact with. The following menu items are
required:
File
• Exit
Tools
• Process Report
• Clear
• Save Report

When the Exit menu item is clicked, close the application.

When the Process Report menu item is clicked, capture the selected agent location,
estate agent name, property price, and commission percentage, and display the estate
agent report. The commission is calculated by multiplying the property price by the
commission percentage.

When the Save Report menu item is clicked, save the estate agent report to a text file
named report.txt.

When clicking the Clear Menu item, set the text fields and text area to the default
state

Make use of a class named EstateAgent that contains methods to calculate the estate
agent commission and validate the data. Only valid data should be captured in the
application; the validation rules are:

VALIDATION: Agent Location
RULE: It cannot be empty

VALIDATION: Agent Name
RULE: It cannot be empty.

VALIDATION: Property Price
RULE: Cannot be less than or equal to zero (0)

VALIDATION: Commission Percentage
RULE: Cannot be less than or equal to zero (0)

The EstateAgent class must implement an IEstateAgent interface that contains the
following:
public interface IEstateAgent {
double CalculateCommission(String propertyPrice, String agentCommission);
boolean ValidateData(Data dataToValidate);
}

You are required to write unit tests for the application. Create a test package within
the application you created, which will contain the necessary unit tests.
You are required to write the following unit tests:

Test Name: CalculateCommission_CalculatedSuccessfully()
Test Purpose: To supply the property price and
agent commission percentage to
the Calculate Commission
method. The test will determine
that the correct commission
value is returned.

Test Name: CalculateCommission_CalculatedUnSuccessfully()
Test Purpose: To supply the property price and
agent commission percentage to
the Calculate Commission
method. The test will determine
if there is a calculation error.

Test Name: Validation Test
Test Purpose: You must only write one unit
test to prove that the validation
performs as expected. Examples
can include validating location is
valid, validating name is valid or
validating property price is valid.

Here is an example implementation of the Java GUI application:

```java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class EstateAgentApplication extends JFrame {

private JComboBox<String> locationComboBox;
private JTextField agentNameField;
private JTextField propertyPriceField;
private JTextField commissionPercentageField;
private JTextArea reportTextArea;

public EstateAgentApplication() {
setTitle("Estate Agent Commission");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);

// Create the menu bar
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);

// Create the file menu
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);

// Create the exit menu item
JMenuItem exitMenuItem = new JMenuItem("Exit");
fileMenu.add(exitMenuItem);
exitMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});

// Create the tools menu
JMenu toolsMenu = new JMenu("Tools");
menuBar.add(toolsMenu);

// Create the process report menu item
JMenuItem processReportMenuItem = new JMenuItem("Process Report");
toolsMenu.add(processReportMenuItem);
processReportMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
processReport();
}
});

// Create the save report menu item
JMenuItem saveReportMenuItem = new JMenuItem("Save Report");
toolsMenu.add(saveReportMenuItem);
saveReportMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
saveReport();
}
});

// Create the clear menu item
JMenuItem clearMenuItem = new JMenuItem("Clear");
toolsMenu.add(clearMenuItem);
clearMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clearFields();
}
});

// Create the form panel
JPanel formPanel = new JPanel(new GridLayout(4, 2));
add(formPanel, BorderLayout.NORTH);

JLabel locationLabel = new JLabel("Location:");
locationComboBox = new JComboBox<>(new String[]{"Cape Town", "Durban", "Pretoria"});
formPanel.add(locationLabel);
formPanel.add(locationComboBox);

JLabel agentNameLabel = new JLabel("Agent Name:");
agentNameField = new JTextField();
formPanel.add(agentNameLabel);
formPanel.add(agentNameField);

JLabel propertyPriceLabel = new JLabel("Property Price:");
propertyPriceField = new JTextField();
formPanel.add(propertyPriceLabel);
formPanel.add(propertyPriceField);

JLabel commissionPercentageLabel = new JLabel("Commission Percentage:");
commissionPercentageField = new JTextField();
formPanel.add(commissionPercentageLabel);
formPanel.add(commissionPercentageField);

// Create the report text area
reportTextArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(reportTextArea);
add(scrollPane, BorderLayout.CENTER);
}

private void processReport() {
String location = locationComboBox.getSelectedItem().toString();
String agentName = agentNameField.getText();
String propertyPriceStr = propertyPriceField.getText();
String commissionPercentageStr = commissionPercentageField.getText();

EstateAgent estateAgent = new EstateAgent();
Data inputData = new Data(location, agentName, propertyPriceStr, commissionPercentageStr);

if (estateAgent.validateData(inputData)) {
double propertyPrice = Double.parseDouble(propertyPriceStr);
double commissionPercentage = Double.parseDouble(commissionPercentageStr);

double commission = estateAgent.calculateCommission(propertyPrice, commissionPercentage);

String report = "Estate Agent Report\n\n" +
"Location: " + location + "\n" +
"Agent Name: " + agentName + "\n" +
"Property Price: " + propertyPrice + "\n" +
"Commission Percentage: " + commissionPercentage + "\n" +
"Commission Earned: " + commission;

reportTextArea.setText(report);
} else {
JOptionPane.showMessageDialog(this, "Invalid data entered. Please check your input.", "Error", JOptionPane.ERROR_MESSAGE);
}
}

private void saveReport() {
try (PrintWriter writer = new PrintWriter(new FileWriter("report.txt"))) {
writer.write(reportTextArea.getText());
JOptionPane.showMessageDialog(this, "Report saved successfully.", "Success", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Error saving report.", "Error", JOptionPane.ERROR_MESSAGE);
}
}

private void clearFields() {
locationComboBox.setSelectedIndex(0);
agentNameField.setText("");
propertyPriceField.setText("");
commissionPercentageField.setText("");
reportTextArea.setText("");
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new EstateAgentApplication().setVisible(true);
}
});
}
}
```

Here is an example implementation of the EstateAgent class:

```java
public class EstateAgent implements IEstateAgent {

@Override
public double calculateCommission(double propertyPrice, double agentCommission) {
return propertyPrice * agentCommission / 100.0;
}

@Override
public boolean validateData(Data dataToValidate) {
String location = dataToValidate.getLocation();
String agentName = dataToValidate.getAgentName();
String propertyPriceStr = dataToValidate.getPropertyPrice();
String commissionPercentageStr = dataToValidate.getCommissionPercentage();

if (location.isEmpty() || agentName.isEmpty() || propertyPriceStr.isEmpty() || commissionPercentageStr.isEmpty()) {
return false;
}

double propertyPrice = Double.parseDouble(propertyPriceStr);
double commissionPercentage = Double.parseDouble(commissionPercentageStr);

if (propertyPrice <= 0 || commissionPercentage <= 0) {
return false;
}

return true;
}
}
```

Here is an example implementation of the IEstateAgent interface:

```java
public interface IEstateAgent {
double calculateCommission(double propertyPrice, double agentCommission);
boolean validateData(Data dataToValidate);
}
```

Here is an example implementation of the Data class:

```java
public class Data {
private String location;
private String agentName;
private String propertyPrice;
private String commissionPercentage;

public Data(String location, String agentName, String propertyPrice, String commissionPercentage) {
this.location = location;
this.agentName = agentName;
this.propertyPrice = propertyPrice;
this.commissionPercentage = commissionPercentage;
}

public String getLocation() {
return location;
}

public String getAgentName() {
return agentName;
}

public String getPropertyPrice() {
return propertyPrice;
}

public String getCommissionPercentage() {
return commissionPercentage;
}
}
```

Here is an example implementation of the unit tests:

```java
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class EstateAgentTest {

@Test
public void calculateCommission_CalculatedSuccessfully() {
EstateAgent estateAgent = new EstateAgent();
double propertyPrice = 1000000;
double commissionPercentage = 5;
double expectedCommission = propertyPrice * commissionPercentage / 100.0;

double actualCommission = estateAgent.calculateCommission(propertyPrice, commissionPercentage);

assertEquals(expectedCommission, actualCommission);
}

@Test
public void calculateCommission_CalculatedUnSuccessfully() {
EstateAgent estateAgent = new EstateAgent();
double propertyPrice = -1000000;
double commissionPercentage = 5;

double actualCommission = estateAgent.calculateCommission(propertyPrice, commissionPercentage);

assertTrue(Double.isNaN(actualCommission));
}

@Test
public void validateData_ValidData_ReturnsTrue() {
EstateAgent estateAgent = new EstateAgent();
Data data = new Data("Cape Town", "John Doe", "1000000", "5");

boolean isValid = estateAgent.validateData(data);

assertTrue(isValid);
}

@Test
public void validateData_InvalidLocation_ReturnsFalse() {
EstateAgent estateAgent = new EstateAgent();
Data data = new Data("", "John Doe", "1000000", "5");

boolean isValid = estateAgent.validateData(data);

assertFalse(isValid);
}

@Test
public void validateData_InvalidPropertyPrice_ReturnsFalse() {
EstateAgent estateAgent = new EstateAgent();
Data data = new Data("Cape Town", "John Doe", "-1000000", "5");

boolean isValid = estateAgent.validateData(data);

assertFalse(isValid);
}

@Test
public void validateData_InvalidCommissionPercentage_ReturnsFalse() {
EstateAgent estateAgent = new EstateAgent();
Data data = new Data("Cape Town", "John Doe", "1000000", "-5");

boolean isValid = estateAgent.validateData(data);

assertFalse(isValid);
}
}
```

Please note that this is just one possible implementation of the requested application. You can modify the code based on your specific requirements or design preferences.