Skip to content
Snippets Groups Projects
Commit f3c56f9d authored by Andre Hartig's avatar Andre Hartig
Browse files

Added OperationService to create Operations

parent 76f148b1
No related branches found
No related tags found
No related merge requests found
...@@ -32,6 +32,12 @@ ...@@ -32,6 +32,12 @@
<artifactId>jackson-core</artifactId> <artifactId>jackson-core</artifactId>
<version>2.13.0</version> <version>2.13.0</version>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Optional;
/**
* Operation class with its attributes, filters and commands.
* @param id unique id of the operation
* @param date the planned date of the operation
* @param startTime the planned starting time of the operation
* @param endTime the planned ending time of the operation
*/
public record Operation(
Id<Operation> id,
LocalDate date,
LocalTime startTime,
LocalTime endTime
) {
/**
* Operation filter
* @param date filter with date
*/
public static final record Filter(
Optional<LocalDate> date
) {
public static final Filter NONE =
new Filter(
Optional.empty()
);
}
/**
* Operation commands
*/
public static sealed interface Command permits Create { }
/**
* Create command to create a new Operation
* @param date the date of the new Operation
* @param startTime the starting time of the new Operation
* @param endTime the ending time of the new Operation
*/
public static record Create(
LocalDate date,
LocalTime startTime,
LocalTime endTime
) implements Command {}
}
import java.util.List;
import java.util.Optional;
/**
* Available Services for Operations
*/
public interface OperationService {
/**
* Processes the possible commands for an Operation
* @param cmd the command to process
* @return the processed Operation
*/
public Operation process(Operation.Command cmd) throws Exception;
/**
* Gets the Operation by ID
* @param id the ID of the Operation
* @return the Operation
*/
public Optional<Operation> getOperation(Id<Operation> id);
/**
* Gets a list of Operations that are matching the filter
* @param filter the filter to match
* @return the matching Operations
*/
public List<Operation> getOperations(Operation.Filter filter);
}
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.LocalDate;
public record Person (
@JsonProperty
Id<Person> id,
@JsonProperty
Gender gender,
@JsonProperty
String givenName,
@JsonProperty
String familyName,
@JsonProperty
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
LocalDate birthDate,
@JsonProperty
Address address
) {
}
import java.util.List;
import java.util.Optional; import java.util.Optional;
public interface Repository { public interface Repository {
/*
Id<Patient> patientId(); Id<Patient> patientId();
void createPatient(Patient patient) throws Exception; void createPatient(Patient patient) throws Exception;
...@@ -9,6 +10,33 @@ public interface Repository { ...@@ -9,6 +10,33 @@ public interface Repository {
Optional<Patient> findPatient(Id<Patient> id); Optional<Patient> findPatient(Id<Patient> id);
Optional<Patient> deletePatient(Id<Patient> id) throws Exception; Optional<Patient> deletePatient(Id<Patient> id) throws Exception;
*/
// Hier dann die restlichen create/edit Methoden rein // Hier dann die restlichen create/edit Methoden rein
/**
* Return an unused operation ID.
* @return Operation ID
*/
Id<Operation> operationId();
/**
* Saves the Operation into the database.
* @param operation the Operation to save into the database
* @throws Exception while saving
*/
void save(Operation operation) throws Exception;
/**
* Returns the Operation with the given ID.
* @param id the ID to search for
* @return the found Operation
*/
Optional<Operation> findOperation(Id<Operation> id);
/**
* Returns a list of all operation entries matching the filter.
* @param filter the filter
* @return the matching entries
*/
List<Operation> findOperations(Operation.Filter filter);
} }
import java.sql.*; import java.sql.*;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import static java.util.UUID.randomUUID; import static java.util.UUID.randomUUID;
/**
* The implemented Repository Interface for SQL-Databases.
*/
class JDBCRepository implements Repository class JDBCRepository implements Repository
{ {
...@@ -16,7 +21,10 @@ class JDBCRepository implements Repository ...@@ -16,7 +21,10 @@ class JDBCRepository implements Repository
} }
// Factory method /**
* Sets up a connection with the repository database via the set url, user and password.
* @return the connected repository
*/
static JDBCRepository instance(){ static JDBCRepository instance(){
try { try {
var conn = var conn =
...@@ -34,44 +42,39 @@ class JDBCRepository implements Repository ...@@ -34,44 +42,39 @@ class JDBCRepository implements Repository
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
private static final String CREATE_PATIENT_TABLE = """
CREATE TABLE IF NOT EXISTS patients(
id VARCHAR(50) PRIMARY KEY,
gender VARCHAR(10) NOT NULL,
givenName VARCHAR(100) NOT NULL,
familyName VARCHAR(100) NOT NULL,
birthDate DATE NOT NULL,
street VARCHAR(50) NOT NULL,
house VARCHAR(50) NOT NULL,
postalCode VARCHAR(50) NOT NULL,
city VARCHAR(50) NOT NULL,
healthInsurance VARCHAR(40) NOT NULL
);
""";
// Set up DB tables etc. /**
* Sets up the database tables.
*/
void setup(){ void setup(){
try (var stmt = conn.createStatement()){ try (var stmt = conn.createStatement()){
stmt.execute(CREATE_PATIENT_TABLE); stmt.execute(CREATE_OPERATION_TABLE);
} catch (SQLException e){ } catch (SQLException e){
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/**
* Sets quotes around the given string.
* @param s the string
* @return the quoted string
*/
private static String quoted(String s){ private static String quoted(String s){
return String.format("'%s'",s); return String.format("'%s'",s);
} }
/**
* Turns a given object into a SQL-value.
* @param obj the object
* @return the SQL-value of the object
*/
private static String sqlValue(Object obj){ private static String sqlValue(Object obj){
return switch(obj){ return switch(obj){
case LocalDate date -> quoted(Date.valueOf(date).toString()); case LocalDate date -> quoted(Date.valueOf(date).toString());
case LocalTime time -> quoted(Time.valueOf(time).toString());
case Instant t -> quoted(Timestamp.from(t).toString()); case Instant t -> quoted(Timestamp.from(t).toString());
case Integer n -> Integer.toString(n); case Integer n -> Integer.toString(n);
case Long n -> Long.toString(n); case Long n -> Long.toString(n);
...@@ -81,6 +84,21 @@ class JDBCRepository implements Repository ...@@ -81,6 +84,21 @@ class JDBCRepository implements Repository
} }
/*
private static final String CREATE_PATIENT_TABLE = """
CREATE TABLE IF NOT EXISTS patients(
id VARCHAR(50) PRIMARY KEY,
gender VARCHAR(10) NOT NULL,
givenName VARCHAR(100) NOT NULL,
familyName VARCHAR(100) NOT NULL,
birthDate DATE NOT NULL,
street VARCHAR(50) NOT NULL,
house VARCHAR(50) NOT NULL,
postalCode VARCHAR(50) NOT NULL,
city VARCHAR(50) NOT NULL,
healthInsurance VARCHAR(40) NOT NULL
);
""";
private static Patient readPatientFromRow(ResultSet rs) throws SQLException { private static Patient readPatientFromRow(ResultSet rs) throws SQLException {
return new Patient( return new Patient(
...@@ -134,8 +152,6 @@ class JDBCRepository implements Repository ...@@ -134,8 +152,6 @@ class JDBCRepository implements Repository
"WHERE id = " + sqlValue(patient.id().value()) + ";"; "WHERE id = " + sqlValue(patient.id().value()) + ";";
} }
@Override @Override
public Id<Patient> patientId(){ public Id<Patient> patientId(){
...@@ -144,7 +160,6 @@ class JDBCRepository implements Repository ...@@ -144,7 +160,6 @@ class JDBCRepository implements Repository
return findPatient(id).isEmpty() ? id : patientId(); return findPatient(id).isEmpty() ? id : patientId();
} }
@Override @Override
public void createPatient(Patient patient) throws SQLException { public void createPatient(Patient patient) throws SQLException {
...@@ -164,7 +179,6 @@ class JDBCRepository implements Repository ...@@ -164,7 +179,6 @@ class JDBCRepository implements Repository
} }
@Override @Override
public Optional<Patient> findPatient(Id<Patient> id){ public Optional<Patient> findPatient(Id<Patient> id){
try ( try (
...@@ -182,7 +196,6 @@ class JDBCRepository implements Repository ...@@ -182,7 +196,6 @@ class JDBCRepository implements Repository
} }
} }
@Override @Override
public Optional<Patient> deletePatient(Id<Patient> id) throws SQLException { public Optional<Patient> deletePatient(Id<Patient> id) throws SQLException {
...@@ -201,6 +214,154 @@ class JDBCRepository implements Repository ...@@ -201,6 +214,154 @@ class JDBCRepository implements Repository
return patient; return patient;
} }
*/
// Hier dann die restlichen create/edit Methoden rein
/**
* The structure of the operations table.
*/
private static final String CREATE_OPERATION_TABLE = """
CREATE TABLE IF NOT EXISTS operations(
id VARCHAR(50) PRIMARY KEY,
date DATE NOT NULL,
startTime TIME NOT NULL,
endTime TIME NOT NULL
);
""";
/**
* Creates the insert statement of the given operation for SQL.
* @param operation the operation to turn into an insert SQL statement
* @return the SQL statement
*/
private static String insertSQL(Operation operation){
return
"INSERT INTO operations(" +
"id,date,startTime,endTime" +
") VALUES (" +
sqlValue(operation.id().value()) + "," +
sqlValue(operation.date()) + "," +
sqlValue(operation.startTime()) + "," +
sqlValue(operation.endTime()) +
");";
}
/**
* Creates the update statement of the given operation for SQL.
* @param operation the operation to turn into an update SQL statement
* @return the SQL statement
*/
private static String updateSQL(Operation operation){
return
"UPDATE operations SET " +
"date = " + sqlValue(operation.date()) + "," +
"startTime = " + sqlValue(operation.startTime()) + "," +
"endTime = " + sqlValue(operation.endTime()) + " " +
"WHERE id = " + sqlValue(operation.id().value()) + ";";
}
/**
* Returns a new generated ID in the operations-SQLTable
* If the generated ID is already used, generate another one.
* @return Operation ID
*/
@Override
public Id<Operation> operationId() {
var id = new Id<Operation>(randomUUID().toString());
return findOperation(id).isEmpty() ? id : operationId();
}
/**
* Connects to the database and checks if the ID of the given Operation is already used.
* If yes, then update existing entry, else insert new entry.
* @param operation the Operation to save into the database
*/
@Override
public void save(Operation operation) {
try (
var stmt = conn.createStatement()
){
var sql =
findOperation(operation.id()).isPresent() ?
updateSQL(operation) :
insertSQL(operation);
stmt.executeUpdate(sql);
} catch (SQLException e){
throw new RuntimeException(e);
}
}
/**
* Reads an Operation from the Operations-SQLTable with the given ID.
* If no Operation with this ID is found, it will return an empty Optional.
* @param id the ID to search for
* @return the found Operation
*/
@Override
public Optional<Operation> findOperation(Id<Operation> id){
try (
var result =
conn.createStatement()
.executeQuery("SELECT * FROM operations WHERE id = " + sqlValue(id.value()) + ";")
){
return
result.next() ?
Optional.of(readOperationFromRow(result)) :
Optional.empty();
} catch (SQLException e){
throw new RuntimeException(e);
}
}
/**
* Connects to the database and searches all filter criteria.
* Adds each found Operation to the list.
* @param filter the filter
* @return the matching entries
*/
@Override
public List<Operation> findOperations(Operation.Filter filter) {
var sql = "SELECT * FROM operations WHERE date = " + filter.date() + ";";
try (
var resultSet =
conn.createStatement().executeQuery(sql)
){
var operations = new ArrayList<Operation>();
while(resultSet.next()){
operations.add(readOperationFromRow(resultSet));
}
return operations;
} catch (SQLException e){
throw new RuntimeException(e);
}
}
/**
* Creates an Operation object with the given result of a read SQL-Row.
* @param rs the result of a read SQL-Row
* @return the created operation object
* @throws SQLException Error while reading the SQL-Row
*/
private static Operation readOperationFromRow(ResultSet rs) throws SQLException {
return new Operation(
new Id<>(rs.getString("id")),
rs.getDate("date").toLocalDate(),
rs.getTime("startTime").toLocalTime(),
rs.getTime("endTime").toLocalTime()
);
}
} }
import java.util.List;
import java.util.Optional;
/**
* The implemented Services of the Operations
*/
public class OperationServiceImpl implements OperationService {
private final Repository repo;
public OperationServiceImpl(Repository repo) {
this.repo = repo;
}
@Override
public Operation process(Operation.Command cmd) throws Exception {
return switch (cmd){
case Operation.Create cr -> create(cr);
};
}
@Override
public Optional<Operation> getOperation(Id<Operation> id) {
return repo.findOperation(id);
}
@Override
public List<Operation> getOperations(Operation.Filter filter) {
return repo.findOperations(filter);
}
public Operation create(Operation.Create cr) throws Exception {
Operation operation =
new Operation(
repo.operationId(),
cr.date(),
cr.startTime(),
cr.endTime());
repo.save(operation);
return operation;
}
}
...@@ -2,6 +2,9 @@ import org.junit.BeforeClass; ...@@ -2,6 +2,9 @@ import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Optional;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
...@@ -12,7 +15,11 @@ public final class Tests ...@@ -12,7 +15,11 @@ public final class Tests
private static Repository repo = null; private static Repository repo = null;
private static Patient testPatient = null; private static OperationService opService;
//private static Patient testPatient = null;
private static Operation testOperation = null;
@BeforeClass @BeforeClass
public static void init() throws Exception { public static void init() throws Exception {
...@@ -23,6 +30,7 @@ public final class Tests ...@@ -23,6 +30,7 @@ public final class Tests
repo = JDBCRepository.instance(); repo = JDBCRepository.instance();
/*
testPatient = new Patient( testPatient = new Patient(
new Id<>("1111"), new Id<>("1111"),
Gender.MALE, Gender.MALE,
...@@ -31,8 +39,18 @@ public final class Tests ...@@ -31,8 +39,18 @@ public final class Tests
LocalDate.of(1999, 01, 01), LocalDate.of(1999, 01, 01),
new Address("Musterstraße", "12", "12345", "Beispielhausen"), new Address("Musterstraße", "12", "12345", "Beispielhausen"),
"AOK"); "AOK");
*/
testOperation = new Operation(
new Id<>("1111"),
LocalDate.of(2024, 05, 24),
LocalTime.of(13, 35, 00),
LocalTime.of(14, 00, 00));
opService = new OperationServiceImpl(repo);
} }
/*
@Test @Test
public void testPatientSave(){ public void testPatientSave(){
...@@ -61,4 +79,31 @@ public final class Tests ...@@ -61,4 +79,31 @@ public final class Tests
repo.findPatient(testPatient.id()).isEmpty() repo.findPatient(testPatient.id()).isEmpty()
); );
} }
*/
@Test
public void testOperationSave(){
try {
repo.save(testOperation);
} catch (Exception e){
e.printStackTrace();
}
assertTrue(
repo.findOperation(testOperation.id()).isPresent()
);
}
@Test
public void testCreateOperation() throws Exception {
Operation.Command createCommand = new Operation.Create(
LocalDate.of(2025, 05, 11),
LocalTime.of(10, 30, 00),
LocalTime.of(11, 00, 00));
Operation operation = opService.process(createCommand);
System.out.println(operation);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment