---
title: "Jam 07 - Exercise 5: System Integration"
tags:
- 2 ๐ in writing
- 3 ๐งช in testing
- 4 ๐ฅณ done
- inheritance
- interfaces
- polymorphism
- uml
- abstract-classes
- junit
---
<!-- markdownlint-disable line-length single-h1 no-inline-html -->
<!-- markdownlint-configure-file { "ul-indent": { "indent": 4 }, "link-fragments": {"ignore_case": true} } -->
{%hackmd dJZ5TulxSDKme-3fSY4Lbw %}
# Exercise 5 - System Integration
## Overview - Exercise 5
You've worked incredibly hard implementing interfaces, exceptions, inheritance hierarchies, and state diagrams! ๐ Now it's time to bring everything together. Rather than having you write all the integration code from scratch, we'll provide you with a well-structured implementation that ties all your components together. Your task is to understand how these pieces work together and why certain design choices were made.
This approach mirrors real-world development, where you often need to:
- Read and understand existing code
- See how different components interact
- Learn from established patterns and practices
- Make informed modifications to complex systems
As you review the code, think about:
- How the Employee hierarchy controls access to Register operations
- How the Searchable interface enables unified search across different types
- How exceptions help maintain system integrity
- How state management ensures proper operation sequencing
Let's dive in and see how all your hard work comes together! ๐
Note: I'm about 92% certain this implementation *should* work regardless of how you implemented your code. If you get stuck and something doesn't work, post on Discord!
## Step 1: Add Employee Field to Register
First, let's add the `currentUser` field to the Register class:
```java
public class Register {
// ... existing fields ...
private Employee currentUser; // Add this field
// ... existing methods ...
}
```
## Step 2: Add Login/Logout Methods
Add these methods to the Register class:
```java
public class Register {
// ... existing code ...
public boolean login(Employee employee) {
if (currentUser != null) {
return false; // Already logged in
}
currentUser = employee;
return true;
}
public boolean logout() {
if (currentUser == null) {
return false; // Already logged out
}
currentUser = null;
return true;
}
public Employee getCurrentUser() {
return currentUser;
}
}
```
## Step 3: Add Permission Check Method
Add this method to check if the current user has permission for an operation:
```java
public class Register {
// ... existing code ...
private boolean shouldBlockOperation(boolean requiresAdmin) {
if (currentUser == null) {
return true; // No user logged in means operation should be blocked
}
if (requiresAdmin) {
return !currentUser.hasAdminPrivileges(); // Block if user doesn't have admin privileges
}
return !currentUser.canAccessRegister(); // Block if user can't access register
}
}
```
## Step 4: Update Transaction Methods
Now let's update the transaction methods to require login:
```java
public class Register {
// ... existing code ...
public boolean startTransaction() {
if (shouldBlockOperation(false)) {
return false;
}
// ... existing startTransaction code ...
}
public boolean addProductToTransaction(String sku) {
if (shouldBlockOperation(false)) {
return false;
}
// ... existing addProductToTransaction code ...
}
public Map<Money, Integer> processPayment(Map<Money, Integer> payment) {
if (shouldBlockOperation(false)) {
return null;
}
// ... existing processPayment code ...
}
}
```
## Step 5: Create Integration Test
Create a new test file `RegisterIntegrationTest.java` in the `jam07` test folder:
```java
package jam07;
import static org.junit.jupiter.api.Assertions.*;
import jam05.Product;
import jam05.ProductCatalog;
import jam06.Register;
import java.time.LocalDate;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class RegisterIntegrationTest {
private static int registerCounter = 0;
private Register register;
private Cashier cashier;
private Manager manager;
private Product testProduct;
@BeforeEach
void setUp() {
// Set up catalog and register
ProductCatalog catalog = new ProductCatalog();
try {
testProduct = new Product("Test Product", "TEST123", 9.99);
catalog.addProduct(testProduct);
} catch (jam07.InvalidPriceException e) {
System.err.println("Error creating product: " + e.getMessage());
System.exit(1);
}
String registerName = String.format("TEST-%03d", ++registerCounter);
register = Register.createRegister(registerName, catalog);
cashier = new Cashier("C001", "Test Cashier", LocalDate.now());
manager = new Manager("M001", "Test Manager", LocalDate.now());
}
@Test
void shouldRequireLoginForOperations() {
// Test operations without login
assertFalse(register.startTransaction());
assertFalse(register.addProductToTransaction(testProduct.getSku()));
// Login as cashier
assertTrue(register.login(cashier));
// Test operations with login
assertTrue(register.startTransaction());
assertTrue(register.addProductToTransaction(testProduct.getSku()));
}
@Test
void shouldAllowManagerAdminOperations() {
// Login as manager
assertTrue(register.login(manager));
// Test admin operations
assertTrue(manager.hasAdminPrivileges());
}
@Test
void shouldManageUserLoginAndLogout() {
// Initially no user should be logged in
assertNull(register.getCurrentUser());
// Login as cashier
assertTrue(register.login(cashier));
assertEquals(cashier, register.getCurrentUser());
// Try to log-in again (should fail)
assertFalse(register.login(manager));
assertEquals(cashier, register.getCurrentUser()); // Should still be a cashier
// Logout
assertTrue(register.logout());
assertNull(register.getCurrentUser());
// Try to log-out again (should fail)
assertFalse(register.logout());
assertNull(register.getCurrentUser());
}
@Test
void shouldEnforceAdminPrivileges() {
// Log-in as cashier
assertTrue(register.login(cashier));
// Cashier should be able to perform regular operations
assertTrue(register.startTransaction());
assertTrue(register.addProductToTransaction(testProduct.getSku()));
// Cashier should be able to perform basic searches
assertTrue(register.matches("TEST-001")); // Can search register name
assertTrue(register.matches("0")); // Can search drawer balance
// Cashier should not be able to perform admin operations
assertNull(register.getCompletedTransactions());
// Logout and login as manager
assertTrue(register.logout());
assertTrue(register.login(manager));
// Manager should be able to perform both regular and admin operations
assertTrue(register.voidTransaction());
assertTrue(register.startTransaction());
assertTrue(register.addProductToTransaction(testProduct.getSku()));
// Manager should have full search capabilities
assertTrue(register.matches("TEST-001")); // Can search register name
assertTrue(register.matches("0")); // Can search drawer balance
assertFalse(register.searchTransactions("IN_PROGRESS")
.isEmpty()); // Can search transactions
// Manager should be able to perform admin operations
assertNotNull(register.getCompletedTransactions());
}
}
```
## Step 6: Run and Verify Tests
1. Run the tests to verify your implementation:
```bash
# Right click on the test folder in IntelliJ
# Click "Run Tests in 'csci205_jams'"
```
2. Fix any failing tests by:
- Checking error messages
- Verifying method implementations
- Ensuring proper permission checks
- Testing edge cases
## Save Your Work - Exercise 5
**Run all tests to verify your implementation**:
```bash
# Right click on the test folder in IntelliJ
# Click "Run Tests in 'csci205_jams'"
# Ensure all tests pass
```
**Stage your changes**:
```bash
git add src/main/java/jam06/Register.java src/test/java/jam07/EmployeeTest.java src/test/java/jam07/ProductCatalogTest.java src/test/java/jam07/ProductTest.java src/test/java/jam07/RegisterIntegrationTest.java src/test/java/jam07/RegisterTest.java src/test/java/jam07/TransactionTest.java
```
**Verify what files are uncommitted**:
```bash
git status
```
**Commit your work**:
```bash
git commit -m "jam07: Add employee authentication to Register"
```
:::success
๐ **Key Takeaways**
- Components must work together seamlessly
- Integration testing is crucial
- Error handling must be comprehensive
- State management is critical
- Documentation ensures maintainability
- Testing verifies system behavior
:::
Remember: Every great developer started exactly where you did. Keep building, keep learning, and most importantly - be proud of how far you've come! ๐