diff --git a/.idea/sqlDataSources.xml b/.idea/sqlDataSources.xml
index ef907f0..2a3ed74 100644
--- a/.idea/sqlDataSources.xml
+++ b/.idea/sqlDataSources.xml
@@ -30,6 +30,7 @@
+
diff --git a/db/nursingHome.db b/db/nursingHome.db
index 9ce1178..77008e9 100644
Binary files a/db/nursingHome.db and b/db/nursingHome.db differ
diff --git a/src/main/java/de/hitec/nhplus/fixtures/MedicationFixture.java b/src/main/java/de/hitec/nhplus/fixtures/MedicationFixture.java
index 025c222..63510ee 100644
--- a/src/main/java/de/hitec/nhplus/fixtures/MedicationFixture.java
+++ b/src/main/java/de/hitec/nhplus/fixtures/MedicationFixture.java
@@ -12,6 +12,12 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
+import de.hitec.nhplus.Main;
+import de.hitec.nhplus.datastorage.DaoFactory;
+import de.hitec.nhplus.medication.Ingredient;
+import de.hitec.nhplus.medication.Medication;
+import de.hitec.nhplus.medication.database.MedicationDao;
+
/**
* {@link Fixture} for {@link Medication}.
*
@@ -20,11 +26,13 @@ import java.util.*;
public class MedicationFixture implements Fixture {
private static final String SCHEMA = "/de/hitec/nhplus/medication/database/Medication.sql";
private static final String INGREDIENT_SCHEMA = "/de/hitec/nhplus/medication/database/Medication_Ingredient.sql";
+ private static final String ALTERNATIVE_SCHEMA = "/de/hitec/nhplus/medication/database/Medication_Alternative.sql";
@Override
public void dropTable(Connection connection) throws SQLException {
connection.createStatement().execute("DROP TABLE IF EXISTS medication");
- connection.createStatement().execute("DROP TABLE IF EXISTS medication_ingredient");
+ connection.createStatement().execute("DROP TABLE IF EXISTS medication_ingredient");
+ connection.createStatement().execute("DROP TABLE IF EXISTS medication_alternative");
}
@Override
@@ -32,16 +40,25 @@ public class MedicationFixture implements Fixture {
final InputStream schema = Main.class.getResourceAsStream(SCHEMA);
final InputStream ingredientSchema = Main.class.getResourceAsStream(INGREDIENT_SCHEMA);
+ final InputStream alternativeSchema = Main.class.getResourceAsStream(ALTERNATIVE_SCHEMA);
+
assert schema != null;
assert ingredientSchema != null;
+ assert alternativeSchema != null;
+
String SQL = new Scanner(schema, StandardCharsets.UTF_8)
- .useDelimiter("\\A")
- .next();
+ .useDelimiter("\\A")
+ .next();
String ingredientSQL = ";" + new Scanner(ingredientSchema, StandardCharsets.UTF_8)
- .useDelimiter("\\A")
- .next();
+ .useDelimiter("\\A")
+ .next();
+ String alternativeSQL = ";" + new Scanner(alternativeSchema, StandardCharsets.UTF_8)
+ .useDelimiter("\\A")
+ .next();
+
connection.createStatement().execute(SQL);
connection.createStatement().execute(ingredientSQL);
+ connection.createStatement().execute(alternativeSQL);
}
@@ -67,55 +84,59 @@ public class MedicationFixture implements Fixture {
Ingredient warfarinnatrium = new Ingredient("Warfarinnatrium");
medications.add(new Medication(
- "Metformin",
- "AstraZeneca",
- List.of(
- metforminhydrochlorid,
- cellulose,
- povidon,
- magnesiumstearat
- ),
- "Übelkeit, Durchfall, Laktatazidose (selten)",
- "Oral",
- 100
+ "Metformin",
+ "AstraZeneca",
+ List.of(
+ metforminhydrochlorid,
+ cellulose,
+ povidon,
+ magnesiumstearat
+ ),
+ "Übelkeit, Durchfall, Laktatazidose (selten)",
+ "Oral",
+ 100,
+ new ArrayList<>()
));
medications.add(new Medication(
- "Lisinopril",
- "Teva Pharmaceuticals",
- List.of(
- lisinoprilDihydrat,
- mannitol,
- calciumphosphat,
- magnesiumstearat
- ),
- "Schwindel, trockener Husten",
- "Oral",
- 150
+ "Lisinopril",
+ "Teva Pharmaceuticals",
+ List.of(
+ lisinoprilDihydrat,
+ mannitol,
+ calciumphosphat,
+ magnesiumstearat
+ ),
+ "Schwindel, trockener Husten",
+ "Oral",
+ 150,
+ new ArrayList<>()
));
medications.add(new Medication(
- "Simvastatin",
- "Mylan",
- List.of(
- simvastatin,
- laktose,
- cellulose,
- magnesiumstearat
- ),
- "Muskelschmerzen, Leberprobleme(selten)",
- "Oral",
- 80
+ "Simvastatin",
+ "Mylan",
+ List.of(
+ simvastatin,
+ laktose,
+ cellulose,
+ magnesiumstearat
+ ),
+ "Muskelschmerzen, Leberprobleme(selten)",
+ "Oral",
+ 80,
+ new ArrayList<>()
));
medications.add(new Medication(
- "Enoxaparin",
- "Sanofi",
- List.of(
- enoxaparinNatrium,
- benzylalkohol,
- wasser
- ),
- "Blutungen, Reaktionen an der Injektionsstelle",
- "Unterhautinjektion",
- 120
+ "Enoxaparin",
+ "Sanofi",
+ List.of(
+ enoxaparinNatrium,
+ benzylalkohol,
+ wasser
+ ),
+ "Blutungen, Reaktionen an der Injektionsstelle",
+ "Unterhautinjektion",
+ 120,
+ new ArrayList<>()
));
Medication deprecatedMedication = new Medication(
"Levothyroxin",
@@ -128,27 +149,43 @@ public class MedicationFixture implements Fixture {
),
"Herzrasen, Gewichtsverlust",
"Oral",
- 90
+ 90,
+ new ArrayList<>()
);
deprecatedMedication.setIsDeprecated(true);
medications.add(deprecatedMedication);
medications.add(new Medication(
- "Warfarin",
- "Apotex Inc.",
- List.of(
- warfarinnatrium,
- laktose,
- staerke,
- magnesiumstearat
- ),
- "Blutungen, Blutergüsse",
- "Oral",
- 110
+ "Warfarin",
+ "Apotex Inc.",
+ List.of(
+ warfarinnatrium,
+ laktose,
+ staerke,
+ magnesiumstearat
+ ),
+ "Blutungen, Blutergüsse",
+ "Oral",
+ 110,
+ new ArrayList<>()
));
MedicationDao dao = DaoFactory.getInstance().createMedicationDAO();
- Map medicationsByName = new HashMap<>();
for (Medication medication : medications) {
dao.create(medication);
+ }
+ List createdMedications = dao.readAll();
+ Map medicationsByName = new HashMap<>();
+ for (Medication medication : createdMedications){
+ switch (medication.getName()){
+ case "Warfarin":
+ medication.setAlternativeMedication(List.of(
+ createdMedications.get(0),
+ createdMedications.get(3)
+ ));
+ break;
+ default:
+ break;
+ }
+ dao.update(medication);
medicationsByName.put(medication.getName(), medication);
}
return medicationsByName;
diff --git a/src/main/java/de/hitec/nhplus/medication/AllMedicationController.java b/src/main/java/de/hitec/nhplus/medication/AllMedicationController.java
index 769a787..06ef522 100644
--- a/src/main/java/de/hitec/nhplus/medication/AllMedicationController.java
+++ b/src/main/java/de/hitec/nhplus/medication/AllMedicationController.java
@@ -53,6 +53,8 @@ public class AllMedicationController {
@FXML
private TableColumn columnCurrentStock;
@FXML
+ public TableColumn columnAlternativeMedication;
+ @FXML
public Button buttonChangeAvailable;
@FXML
public Button buttonAdd;
@@ -63,6 +65,10 @@ public class AllMedicationController {
private MedicationDao dao;
private boolean hasEditPermissions;
+ public MedicationDao getDao() {
+ return dao;
+ }
+
/**
* Initialization method that is called after the binding of all the fields.
*/
@@ -87,13 +93,29 @@ public class AllMedicationController {
return new SimpleStringProperty(
ingredients
.stream()
- .map(ingredient -> ingredient.getName())
+ .map(Ingredient::getName)
.collect(Collectors.joining("\n"))
);
});
this.columnPossibleSideEffects.setCellValueFactory(new PropertyValueFactory<>("possibleSideEffects"));
this.columnAdministrationMethod.setCellValueFactory(new PropertyValueFactory<>("administrationMethod"));
this.columnCurrentStock.setCellValueFactory(new PropertyValueFactory<>("currentStock"));
+ this.columnAlternativeMedication.setCellValueFactory(
+ cellData -> {
+ Medication medication = cellData.getValue();
+ List alternatives = medication.getAlternativeMedication();
+ if (alternatives.isEmpty()) {
+ return new SimpleStringProperty("");
+ }
+
+ return new SimpleStringProperty(
+ alternatives
+ .stream()
+ .map(med -> med.getName() + ", " + med.getManufacturer())
+ .collect(Collectors.joining("\n"))
+ );
+ }
+ );
this.tableView.setItems(this.medications);
@@ -217,5 +239,4 @@ public class AllMedicationController {
}
});
}
-
}
diff --git a/src/main/java/de/hitec/nhplus/medication/DeprecatedMedicationController.java b/src/main/java/de/hitec/nhplus/medication/DeprecatedMedicationController.java
index 03d5947..2389f1b 100644
--- a/src/main/java/de/hitec/nhplus/medication/DeprecatedMedicationController.java
+++ b/src/main/java/de/hitec/nhplus/medication/DeprecatedMedicationController.java
@@ -39,6 +39,8 @@ public class DeprecatedMedicationController {
@FXML
private TableColumn columnCurrentStock;
@FXML
+ public TableColumn columnAlternativeMedication;
+ @FXML
public Button buttonChangeAvailable;
private final ObservableList medications = FXCollections.observableArrayList();
@@ -71,6 +73,22 @@ public class DeprecatedMedicationController {
this.columnPossibleSideEffects.setCellValueFactory(new PropertyValueFactory<>("possibleSideEffects"));
this.columnAdministrationMethod.setCellValueFactory(new PropertyValueFactory<>("administrationMethod"));
this.columnCurrentStock.setCellValueFactory(new PropertyValueFactory<>("currentStock"));
+ this.columnAlternativeMedication.setCellValueFactory(
+ cellData -> {
+ Medication medication = cellData.getValue();
+ List alternatives = medication.getAlternativeMedication();
+ if (alternatives.isEmpty()) {
+ return new SimpleStringProperty("");
+ }
+
+ return new SimpleStringProperty(
+ alternatives
+ .stream()
+ .map(med -> med.getName() + ", " + med.getManufacturer())
+ .collect(Collectors.joining("\n"))
+ );
+ }
+ );
this.tableView.setItems(this.medications);
diff --git a/src/main/java/de/hitec/nhplus/medication/Medication.java b/src/main/java/de/hitec/nhplus/medication/Medication.java
index f33a98e..9720d12 100644
--- a/src/main/java/de/hitec/nhplus/medication/Medication.java
+++ b/src/main/java/de/hitec/nhplus/medication/Medication.java
@@ -18,13 +18,14 @@ import java.util.stream.Collectors;
*/
public class Medication {
private SimpleIntegerProperty id;
- private final SimpleStringProperty name;
- private final SimpleStringProperty manufacturer;
- private final SimpleListProperty ingredients;
- private final SimpleStringProperty possibleSideEffects;
- private final SimpleStringProperty administrationMethod;
- private final SimpleIntegerProperty currentStock;
- private final SimpleBooleanProperty isDeprecated;
+ private SimpleStringProperty name;
+ private SimpleStringProperty manufacturer;
+ private SimpleListProperty ingredients;
+ private SimpleStringProperty possibleSideEffects;
+ private SimpleStringProperty administrationMethod;
+ private SimpleIntegerProperty currentStock;
+ private SimpleListProperty alternativeMedication;
+ private SimpleBooleanProperty isDeprecated;
/**
* This constructor allows instantiating a {@link Medication} object,
@@ -39,7 +40,8 @@ public class Medication {
List ingredients,
String possibleSideEffects,
String administrationMethod,
- int currentStock
+ int currentStock,
+ List alternativeMedication
) {
this.name = new SimpleStringProperty(name);
this.manufacturer = new SimpleStringProperty(manufacturer);
@@ -47,6 +49,7 @@ public class Medication {
this.possibleSideEffects = new SimpleStringProperty(possibleSideEffects);
this.administrationMethod = new SimpleStringProperty(administrationMethod);
this.currentStock = new SimpleIntegerProperty(currentStock);
+ this.alternativeMedication = new SimpleListProperty<>(FXCollections.observableArrayList(alternativeMedication));
this.isDeprecated = new SimpleBooleanProperty(false);
}
@@ -61,6 +64,7 @@ public class Medication {
String possibleSideEffects,
String administrationMethod,
int currentStock,
+ List alternativeMedication,
boolean isDeprecated
) {
this.id = new SimpleIntegerProperty(id);
@@ -70,9 +74,25 @@ public class Medication {
this.possibleSideEffects = new SimpleStringProperty(possibleSideEffects);
this.administrationMethod = new SimpleStringProperty(administrationMethod);
this.currentStock = new SimpleIntegerProperty(currentStock);
+ this.alternativeMedication = new SimpleListProperty<>(FXCollections.observableArrayList(alternativeMedication));
this.isDeprecated = new SimpleBooleanProperty(isDeprecated);
}
+ public void replace(Medication medication){
+ if(medication == null){
+ return;
+ }
+ this.id = medication.idProperty();
+ this.name = medication.nameProperty();
+ this.manufacturer = medication.manufacturerProperty();
+ this.ingredients = medication.ingredientsProperty();
+ this.possibleSideEffects = medication.possibleSideEffectsProperty();
+ this.administrationMethod = medication.administrationMethodProperty();
+ this.currentStock = medication.currentStockProperty();
+ this.alternativeMedication = medication.alternativeMedicationProperty();
+ this.isDeprecated = medication.isDeprecatedProperty();
+ }
+
public int getId() {
return id.get();
}
@@ -141,6 +161,18 @@ public class Medication {
this.possibleSideEffects.set(possibleSideEffects);
}
+ public ObservableList getAlternativeMedication() {
+ return alternativeMedication.get();
+ }
+
+ public SimpleListProperty alternativeMedicationProperty() {
+ return alternativeMedication;
+ }
+
+ public void setAlternativeMedication(List alternativeMedication) {
+ this.alternativeMedication.set(FXCollections.observableArrayList(alternativeMedication));
+ }
+
public String getAdministrationMethod() {
return administrationMethod.get();
}
@@ -179,6 +211,14 @@ public class Medication {
.add("Possible Side Effects: " + this.getPossibleSideEffects())
.add("Administration Method: " + this.getAdministrationMethod())
.add("Current Stock: " + this.getCurrentStock())
+ .add("Alternative Medication" + this.getAlternativeMedication())
.toString();
}
+
+ public String getComboBoxString() {
+ return new StringJoiner(System.lineSeparator())
+ .add("Name: " + this.getName())
+ .add("Hersteller: " + this.getManufacturer())
+ .toString();
+ }
}
diff --git a/src/main/java/de/hitec/nhplus/medication/MedicationListCell.java b/src/main/java/de/hitec/nhplus/medication/MedicationListCell.java
new file mode 100644
index 0000000..fe82287
--- /dev/null
+++ b/src/main/java/de/hitec/nhplus/medication/MedicationListCell.java
@@ -0,0 +1,146 @@
+package de.hitec.nhplus.medication;
+
+import javafx.beans.value.ObservableValue;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.geometry.Insets;
+import javafx.scene.control.Button;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.text.Text;
+import org.controlsfx.control.SearchableComboBox;
+
+import java.util.List;
+
+/**
+ * A custom implementation of the {@link ListCell} for {@link Ingredient}s.
+ * This implementation contains an automatic resizing of the parent {@link ListView}.
+ *
+ * @author Dominik Säume
+ */
+public class MedicationListCell extends ListCell {
+ private final Button deleteButton;
+ private final SearchableComboBox comboBox;
+ private static final double BUILTIN_BORDER_WIDTH = 1;
+ private static final double CELL_SPACING = 4;
+ private static final double CELL_PADDING = 4;
+ private static final double BUTTON_PADDING_X = 8;
+ private static final double BUTTON_PADDING_Y = 4;
+ private final double totalSpacing;
+ private boolean firstUpdate = true;
+
+ public MedicationListCell(List allOtherMedications) {
+ this.setPadding(new Insets(CELL_PADDING));
+
+ comboBox = new SearchableComboBox<>();
+ ObservableList list = FXCollections.observableArrayList();
+ list.setAll(allOtherMedications);
+ comboBox.setItems(list);
+ comboBox.setPromptText("Alternatve Auswählen");
+ comboBox.setCellFactory(this::comboBoxFactory);
+ comboBox.setButtonCell(comboBoxButtonFactory());
+ comboBox.valueProperty().addListener(this::onComboBoxChange);
+
+ deleteButton = new Button("-");
+ deleteButton.setPadding(new Insets(
+ BUTTON_PADDING_Y,
+ BUTTON_PADDING_X,
+ BUTTON_PADDING_Y,
+ BUTTON_PADDING_X
+ ));
+ deleteButton.setOnAction(this::handleDeleteButton);
+
+ // Calculate Delete Button Width
+ Text textNode = new Text(deleteButton.getText());
+ textNode.setFont(deleteButton.getFont());
+ double calculatedDeleteButtonWidth = textNode.getLayoutBounds().getWidth() + BUTTON_PADDING_X * 2;
+
+ totalSpacing = BUILTIN_BORDER_WIDTH * 2 // List View
+ + CELL_PADDING * 2
+ + CELL_SPACING
+ + calculatedDeleteButtonWidth;
+ }
+
+
+ /**
+ * A Callback for use as a Listener for the {@link MedicationListCell#comboBox}.
+ */
+ private void onComboBoxChange(
+ ObservableValue extends Medication> observableValue,
+ Medication oldValue,
+ Medication newValue
+ ) {
+ getItem().replace(comboBox.getValue());
+
+ ListView listView = getListView();
+ double max = listView.lookupAll("*")
+ .stream()
+ .filter(node -> node instanceof MedicationListCell)
+ .mapToDouble(node -> comboBox.getWidth())
+ .max()
+ .orElse(0);
+
+ listView.setMinWidth(max + totalSpacing);
+ }
+
+ @Override
+ protected void updateItem(Medication item, boolean empty) {
+ super.updateItem(item, empty);
+ if (empty || item == null) {
+ setGraphic(null);
+ } else {
+ if (
+ firstUpdate
+ && comboBox.getSelectionModel().getSelectedItem() == null
+ && item.getName() != null
+ && comboBox.getItems().contains(item)
+ ) {
+ comboBox.getSelectionModel().select(item);
+ }
+ firstUpdate = false;
+
+ BorderPane cellPane = new BorderPane();
+ cellPane.setCenter(comboBox);
+ cellPane.setRight(deleteButton);
+ BorderPane.setMargin(deleteButton, new Insets(0, 0, 0, CELL_SPACING));
+ setGraphic(cellPane);
+ }
+ }
+
+ private ListCell comboBoxFactory(Object param) {
+ return new ListCell() {
+
+ @Override
+ protected void updateItem(Medication med, boolean empty) {
+ super.updateItem(med, empty);
+ setText(
+ empty || med == null
+ ? null
+ : med.getComboBoxString()
+ );
+ }
+ };
+ }
+
+ private ListCell comboBoxButtonFactory() {
+ return new ListCell() {
+ @Override
+ protected void updateItem(Medication med, boolean empty) {
+ super.updateItem(med, empty);
+ setText(
+ empty || med == null
+ ? comboBox.getPromptText()
+ : med.getComboBoxString()
+ );
+ }
+ };
+ }
+
+ private void handleDeleteButton(ActionEvent event) {
+ if (getItem() == null) {
+ getListView().getItems().remove(getItem());
+ }
+ }
+}
diff --git a/src/main/java/de/hitec/nhplus/medication/MedicationModalController.java b/src/main/java/de/hitec/nhplus/medication/MedicationModalController.java
index ab80e1d..2bc28e3 100644
--- a/src/main/java/de/hitec/nhplus/medication/MedicationModalController.java
+++ b/src/main/java/de/hitec/nhplus/medication/MedicationModalController.java
@@ -1,6 +1,5 @@
package de.hitec.nhplus.medication;
-import de.hitec.nhplus.treatment.Treatment;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@@ -13,7 +12,10 @@ import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import static de.hitec.nhplus.utils.Validator.*;
@@ -38,13 +40,17 @@ public class MedicationModalController {
public TextArea textAreaPossibleSideEffects;
@FXML
public Button buttonSave;
+ @FXML
+ public ListView listViewAlternativeMedication;
private Stage stage;
private Medication medication;
private final ObservableList ingredients = FXCollections.observableArrayList();
+ private final ObservableList alternativeMediaction = FXCollections.observableArrayList();
private AllMedicationController controller;
private boolean isNewMedication = false;
+ private List allOtherMedications;
/**
* Initialization method that is called after the binding of all the fields.
@@ -68,15 +74,20 @@ public class MedicationModalController {
new ArrayList<>(),
"",
"",
- 0
+ 0,
+ new ArrayList<>()
);
this.buttonSave.setDisable(true);
}
listViewIngredients.setCellFactory(cellData -> new IngredientListCell());
listViewIngredients.setItems(ingredients);
+
showData();
+ listViewAlternativeMedication.setCellFactory(cellData -> new MedicationListCell(allOtherMedications));
+ listViewAlternativeMedication.setItems(alternativeMediaction);
+
ChangeListener inputMedicationValidationListener = (observableValue, oldText, newText) -> {
boolean isValid = isValidMedicationName(textFieldName.getText())
&& isValidMedicationManufacturer(textFieldManufacturer.getText())
@@ -97,6 +108,22 @@ public class MedicationModalController {
*/
private void showData() {
ingredients.setAll(medication.getIngredients());
+ alternativeMediaction.setAll(medication.getAlternativeMedication());
+ Map currentAlternatives = alternativeMediaction
+ .stream()
+ .collect(Collectors.toMap(Medication::getId, med -> med));
+ try {
+ allOtherMedications = controller.getDao().readAll();
+ if (!isNewMedication) {
+ allOtherMedications = allOtherMedications
+ .stream()
+ .filter(med -> med.getId() != medication.getId())
+ .map(med -> currentAlternatives.getOrDefault(med.getId(), med))
+ .toList();
+ }
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
textFieldName.setText(medication.getName());
textFieldManufacturer.setText(medication.getManufacturer());
textFieldAdministrationMethod.setText(medication.getAdministrationMethod());
@@ -120,6 +147,15 @@ public class MedicationModalController {
.toList()
);
+ this.medication.setAlternativeMedication(
+ alternativeMediaction
+ .stream()
+ .distinct()
+ .filter(Predicate.not(Objects::isNull))
+ .filter(Predicate.not(med -> med.idProperty() == null))
+ .toList()
+ );
+
if (isNewMedication) {
controller.createMedication(medication);
} else {
@@ -139,4 +175,16 @@ public class MedicationModalController {
public void handleAddIngredient() {
ingredients.add(new Ingredient(""));
}
+
+ public void handleAddAlternativeMedication() {
+ alternativeMediaction.add(new Medication(
+ null,
+ null,
+ new ArrayList<>(),
+ null,
+ null,
+ -1,
+ new ArrayList<>()
+ ));
+ }
}
diff --git a/src/main/java/de/hitec/nhplus/medication/database/MedicationDao.java b/src/main/java/de/hitec/nhplus/medication/database/MedicationDao.java
index 5e31e43..3fa13e4 100644
--- a/src/main/java/de/hitec/nhplus/medication/database/MedicationDao.java
+++ b/src/main/java/de/hitec/nhplus/medication/database/MedicationDao.java
@@ -8,10 +8,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* The {@link MedicationDao} is an implementation of the{@link de.hitec.nhplus.datastorage.Dao Dao}
@@ -64,36 +61,45 @@ public class MedicationDao implements Dao {
ingredientStatement.setString(2, ingredient.getName());
ingredientStatement.execute();
}
+
+ final String alternativeMedicationSQL = """
+ INSERT INTO medication_alternative
+ (id, alternativeId)
+ VALUES (?, ?);
+ """;
+ for (Medication alternative : medication.getAlternativeMedication()) {
+ PreparedStatement alternativeStatement = this.connection.prepareStatement(alternativeMedicationSQL);
+ alternativeStatement.setInt(1, newId);
+ alternativeStatement.setInt(2, alternative.getId());
+ alternativeStatement.execute();
+ }
}
@Override
public Medication read(int id) throws SQLException {
- final String SQL = """
- SELECT medication.*, medication_ingredient.id
- FROM medication
- LEFT JOIN medication_ingredient ON medication.id = medication_ingredient.id
- WHERE medication.id = ?
- """;
- PreparedStatement statement = this.connection.prepareStatement(SQL);
- statement.setInt(1, id);
- ResultSet result = statement.executeQuery();
+ ResultSet result = getReadStatement(id).executeQuery();
return getInstanceFromResultSet(result);
}
@Override
public List readAll() throws SQLException {
final String SQL = """
- SELECT medication.*, medication_ingredient.name
- FROM medication LEFT JOIN
+ SELECT medication.*, medication_ingredient.name, medication_alternative.alternativeId
+ FROM medication
+ LEFT JOIN
medication_ingredient ON medication.id = medication_ingredient.id
+ LEFT JOIN
+ medication_alternative ON medication.id = medication_alternative.id
""";
ResultSet result = connection.prepareStatement(SQL).executeQuery();
- List medications = new ArrayList<>();
+ Map medications = new HashMap<>();
Map> ingredientMap = new HashMap<>();
+ Map> alternativesMap = new HashMap<>();
int currentMedicationId;
int lastMedicationId = -1;
+ String latIngredient = "";
while (result.next()) {
currentMedicationId = result.getInt(1);
if (currentMedicationId != lastMedicationId) {
@@ -105,125 +111,56 @@ public class MedicationDao implements Dao {
result.getString(4),
result.getString(5),
result.getInt(6),
- result.getBoolean(7)
- );
- medications.add(medication);
- }
- List ingredients = ingredientMap.computeIfAbsent(currentMedicationId, k -> new ArrayList<>());
- String ingredientName = result.getString(8);
- if(ingredientName == null){
- continue;
- }
- ingredients.add(new Ingredient(ingredientName));
- lastMedicationId = currentMedicationId;
- }
- for (Medication medication : medications) {
- List ingredients = ingredientMap.get(medication.getId());
- if(ingredients.isEmpty()){
- continue;
- }
- medication.setIngredients(ingredientMap.get(medication.getId()));
- }
-
- return medications;
- }
-
- public List readAllDeprecated() throws SQLException {
- final String SQL = """
- SELECT medication.*, medication_ingredient.name
- FROM medication LEFT JOIN
- medication_ingredient
- ON medication.id = medication_ingredient.id
- WHERE medication.isDeprecated = true
- """;
- ResultSet result = connection.prepareStatement(SQL).executeQuery();
-
- List medications = new ArrayList<>();
- Map> ingredientMap = new HashMap<>();
-
- int currentMedicationId;
- int lastMedicationId = -1;
- while (result.next()) {
- currentMedicationId = result.getInt(1);
- if (currentMedicationId != lastMedicationId) {
- Medication medication = new Medication(
- result.getInt(1),
- result.getString(2),
- result.getString(3),
new ArrayList<>(),
- result.getString(4),
- result.getString(5),
- result.getInt(6),
result.getBoolean(7)
);
- medications.add(medication);
+ medications.put(currentMedicationId, medication);
}
+
List ingredients = ingredientMap.computeIfAbsent(currentMedicationId, k -> new ArrayList<>());
String ingredientName = result.getString(8);
- if(ingredientName == null){
- continue;
+ if (ingredientName != null && !latIngredient.equals(ingredientName)) {
+ ingredients.add(new Ingredient(ingredientName));
+ latIngredient = ingredientName;
}
- ingredients.add(new Ingredient(ingredientName));
+
+ Set alternatives = alternativesMap.computeIfAbsent(currentMedicationId, k -> new HashSet<>());
+ int alternativeId = result.getInt(9);
+ if (alternativeId != 0) {
+ alternatives.add(alternativeId);
+ }
+
lastMedicationId = currentMedicationId;
}
- for (Medication medication : medications) {
+ for (Medication medication : medications.values()) {
List ingredients = ingredientMap.get(medication.getId());
- if(ingredients.isEmpty()){
+ if (ingredients.isEmpty()) {
continue;
}
medication.setIngredients(ingredientMap.get(medication.getId()));
+ Set alternativeIds = alternativesMap.get(medication.getId());
+ List alternatives = new ArrayList<>();
+ for (Integer alternativeId : alternativeIds) {
+ alternatives.add(medications.get(alternativeId));
+ }
+ medication.setAlternativeMedication(alternatives);
}
- return medications;
+ return medications.values().stream().toList();
}
public List readAllAvailable() throws SQLException {
- final String SQL = """
- SELECT medication.*, medication_ingredient.name
- FROM medication LEFT JOIN
- medication_ingredient
- ON medication.id = medication_ingredient.id
- WHERE medication.isDeprecated = false
- """;
- ResultSet result = connection.prepareStatement(SQL).executeQuery();
+ return readAll()
+ .stream()
+ .filter(med -> !med.isDeprecated())
+ .toList();
+ }
- List medications = new ArrayList<>();
- Map> ingredientMap = new HashMap<>();
-
- int currentMedicationId;
- int lastMedicationId = -1;
- while (result.next()) {
- currentMedicationId = result.getInt(1);
- if (currentMedicationId != lastMedicationId) {
- Medication medication = new Medication(
- result.getInt(1),
- result.getString(2),
- result.getString(3),
- new ArrayList<>(),
- result.getString(4),
- result.getString(5),
- result.getInt(6),
- result.getBoolean(7)
- );
- medications.add(medication);
- }
- List ingredients = ingredientMap.computeIfAbsent(currentMedicationId, k -> new ArrayList<>());
- String ingredientName = result.getString(8);
- if(ingredientName == null){
- continue;
- }
- ingredients.add(new Ingredient(ingredientName));
- lastMedicationId = currentMedicationId;
- }
- for (Medication medication : medications) {
- List ingredients = ingredientMap.get(medication.getId());
- if(ingredients.isEmpty()){
- continue;
- }
- medication.setIngredients(ingredientMap.get(medication.getId()));
- }
-
- return medications;
+ public List readAllDeprecated() throws SQLException {
+ return readAll()
+ .stream()
+ .filter(Medication::isDeprecated)
+ .toList();
}
@Override
@@ -266,6 +203,25 @@ public class MedicationDao implements Dao {
statement.setString(2, ingredient.getName());
statement.execute();
}
+
+ final String alternativeDeleteSQL = """
+ DELETE FROM medication_alternative WHERE id = ?
+ """;
+ PreparedStatement alternativeStatement = this.connection.prepareStatement(alternativeDeleteSQL);
+ alternativeStatement.setInt(1, medication.getId());
+ alternativeStatement.executeUpdate();
+
+ final String alternativeCreateSQL = """
+ INSERT INTO medication_alternative
+ (id, alternativeId)
+ VALUES (?, ?);
+ """;
+ for (Medication alternative : medication.getAlternativeMedication()) {
+ PreparedStatement statement = this.connection.prepareStatement(alternativeCreateSQL);
+ statement.setInt(1, medication.getId());
+ statement.setInt(2, alternative.getId());
+ statement.execute();
+ }
}
@Override
@@ -278,6 +234,23 @@ public class MedicationDao implements Dao {
preparedStatement.executeUpdate();
}
+ /**
+ * @param id The ID of the database entry to read.
+ * @return A {@link PreparedStatement} to read a specific entry by its ID.
+ */
+ public PreparedStatement getReadStatement(int id) throws SQLException {
+ final String SQL = """
+ SELECT medication.*, medication_ingredient.name, medication_alternative.alternativeId
+ FROM medication
+ LEFT JOIN medication_ingredient ON medication.id = medication_ingredient.id
+ LEFT JOIN medication_alternative ON medication.id = medication_alternative.id
+ WHERE medication.id = ?
+ """;
+ PreparedStatement statement = this.connection.prepareStatement(SQL);
+ statement.setInt(1, id);
+ return statement;
+ }
+
/**
* Constructs a {@link Medication} object from the {@link ResultSet} obtained after executing a database query.
* This method is used internally to map the {@link ResultSet} data to a {@link Medication} object.
@@ -290,19 +263,41 @@ public class MedicationDao implements Dao {
result.getInt(1),
result.getString(2),
result.getString(3),
- List.of(),
+ new ArrayList<>(),
result.getString(4),
result.getString(5),
result.getInt(6),
+ new ArrayList<>(),
result.getBoolean(7)
);
List ingredients = new ArrayList<>();
+ List alternatives = new ArrayList<>();
while (result.next()) {
- ingredients.add(new Ingredient(result.getString(2)));
-
+ String ingredientName = result.getString(8);
+ if (ingredientName != null) {
+ ingredients.add(new Ingredient(ingredientName));
+ }
+ int alternativeId = result.getInt(9);
+ if (alternativeId != 0) {
+ ResultSet alternativeResult = getReadStatement(alternativeId).executeQuery();
+ Medication alternativeMedication = new Medication(
+ alternativeResult.getInt(1),
+ alternativeResult.getString(2),
+ alternativeResult.getString(3),
+ new ArrayList<>(),
+ alternativeResult.getString(4),
+ alternativeResult.getString(5),
+ alternativeResult.getInt(6),
+ new ArrayList<>(),
+ alternativeResult.getBoolean(7)
+ );
+ alternatives.add(alternativeMedication);
+ }
}
medication.setIngredients(ingredients);
+ medication.setAlternativeMedication(alternatives);
return medication;
+
}
}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 56fcea2..0c396b4 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -3,6 +3,7 @@ module de.hitec.nhplus {
requires javafx.fxml;
requires java.sql;
requires org.xerial.sqlitejdbc;
+ requires org.controlsfx.controls;
exports de.hitec.nhplus;
opens de.hitec.nhplus to javafx.fxml;
diff --git a/src/main/resources/de/hitec/nhplus/medication/AllMedicationView.fxml b/src/main/resources/de/hitec/nhplus/medication/AllMedicationView.fxml
index 63407cc..d4de0e6 100644
--- a/src/main/resources/de/hitec/nhplus/medication/AllMedicationView.fxml
+++ b/src/main/resources/de/hitec/nhplus/medication/AllMedicationView.fxml
@@ -49,6 +49,11 @@
minWidth="100.0"
text="Lagerbestand"
/>
+
diff --git a/src/main/resources/de/hitec/nhplus/medication/DeprecatedMedicationView.fxml b/src/main/resources/de/hitec/nhplus/medication/DeprecatedMedicationView.fxml
index a39c742..6a89e05 100644
--- a/src/main/resources/de/hitec/nhplus/medication/DeprecatedMedicationView.fxml
+++ b/src/main/resources/de/hitec/nhplus/medication/DeprecatedMedicationView.fxml
@@ -49,6 +49,11 @@
minWidth="100.0"
text="Lagerbestand"
/>
+
diff --git a/src/main/resources/de/hitec/nhplus/medication/MedicationModal.fxml b/src/main/resources/de/hitec/nhplus/medication/MedicationModal.fxml
index c368327..4a4990a 100644
--- a/src/main/resources/de/hitec/nhplus/medication/MedicationModal.fxml
+++ b/src/main/resources/de/hitec/nhplus/medication/MedicationModal.fxml
@@ -3,6 +3,7 @@
+
-
-
-
-
+
@@ -105,10 +103,45 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/de/hitec/nhplus/medication/database/Medication_Alternative.sql b/src/main/resources/de/hitec/nhplus/medication/database/Medication_Alternative.sql
new file mode 100644
index 0000000..76e3364
--- /dev/null
+++ b/src/main/resources/de/hitec/nhplus/medication/database/Medication_Alternative.sql
@@ -0,0 +1,7 @@
+CREATE TABLE medication_alternative
+(
+ id INTEGER NOT NULL ,
+ alternativeId INTEGER NOT NULL ,
+ FOREIGN KEY (id) REFERENCES medication (id) ON DELETE CASCADE,
+ FOREIGN KEY (alternativeId) REFERENCES medication (id) ON DELETE CASCADE
+)
\ No newline at end of file